Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
उपकरण/GitHubGitHub/brianwrf/magento-cve-2016-4010
भेद्यता विश्लेषणकोड विश्लेषणशोषणवेब एप्लिकेशन शोषणपेनिट्रेशन टेस्टिंगलर्निंग और शिक्षालैब और अभ्यास
GitHubbrianwrf/magento-cve-2016-4010

Magento-CVE-2016-4010

Magento अनधिकृत रिमोट कोड निष्पादन (CVE-2016-4010)

रिपॉजिटरी देखें
6310 साल पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

Magento अनधिकृत रिमोट कोड निष्पादन भेद्यता (CVE-2016-4010) का विश्लेषण और शोषण


0x00 परिचय

17 मई को, विदेशी सुरक्षा शोधकर्ता Netanel Rubin ने Magento में एक अनधिकृत रिमोट कोड निष्पादन भेद्यता (CVE-2016-4010) का खुलासा किया। यह भेद्यता वास्तव में कई छोटी भेद्यताओं को समाहित करती है और हमलावर को कमजोर Magento सर्वर पर अनधिकृत रूप से PHP कोड निष्पादित करने की अनुमति देती है। Magento एक अत्यंत लोकप्रिय ई-कॉमर्स प्लेटफ़ॉर्म है, जिसे 2011 में eBay द्वारा अधिग्रहित किया गया था। कुछ प्रसिद्ध कंपनियाँ, जैसे: Samsung, Nikon, Lenovo, तथा कई छोटे ई-कॉमर्स स्टोर इसे उपयोग कर रहे हैं। सूत्रों के अनुसार, Magento का उपयोग 250,000 ऑनलाइन स्टोर करते हैं, जिनमें प्रतिवर्ष लगभग 60 बिलियन अमेरिकी डॉलर के लेन-देन होते हैं।

0x01 विश्लेषण

इस भेद्यता के शोषण की शर्तें:

  • Magento में RPC (REST या SOAP) सक्षम है, तथा अधिकांश स्थितियों में यह डिफ़ॉल्ट रूप से सक्षम रहता है
  • Magento का CE और EE संस्करण <2.0.6

Magento का वेब API RPC के 2 अलग-अलग तरीकों की अनुमति देता है, जिन्हें REST RPC और SOAP API कहा जाता है। ये दोनों तरीके समान कार्यक्षमता प्रदान करते हैं, एकमात्र अंतर यह है कि पहला इनपुट संचारित करने के लिए JSON और HTTP अनुरोधों का उपयोग करता है, जबकि दूसरा XML का उपयोग करता है।

केवल कुछ मॉड्यूलों के API को सार्वजनिक करने के लिए, Magento डेवलपर्स को एक सुविधाजनक तरीका प्रदान करता है, जो "webapi.xml" फ़ाइल में केवल उन्हीं मॉड्यूलों के API को घोषित करना है जिन तक वे पहुँच प्रदान करना चाहते हैं। webapi.xml फ़ाइल में उन सभी वेब API की कक्षाएं (classes) और विधियाँ (methods) शामिल होती हैं जिन्हें सार्वजनिक करने की आवश्यकता होती है, तथा प्रत्येक विधि अपनी आवश्यक विशिष्ट अनुमतियाँ भी निर्दिष्ट करती है। इन अनुमतियों में शामिल हैं:

  • anonymous - ऐसी विधियाँ जिन तक कोई भी व्यक्ति पहुँच सकता है
  • self - केवल पंजीकृत उपयोगकर्ताओं और विशिष्ट व्यवस्थापकों को अनुमति देता है, जैसे: "Magento_Backend::admin" अनुमति केवल उन्हीं व्यवस्थापकों को पहुँच की अनुमति देती है जो सर्वर कॉन्फ़िगरेशन संपादित कर सकते हैं

निःसंदेह, यह तरीका जो डेवलपर्स को webapi.xml फ़ाइल के माध्यम से सिस्टम के फ्रंट-एंड तथा बैक-एंड (वेब API) के बीच संचार करने की अनुमति देता है, वास्तव में मॉड्यूल के कोर में सीधे प्रवेश का एक बैकडोर भी खोल देता है।

इसके अतिरिक्त, भले ही हमारे पास "anonymous" अनुमति हो, फिर भी हमें गतिशील रूप से मान पारित करने का एक तरीका चाहिए। यहाँ तात्पर्य सिस्टम में उपलब्ध विभिन्न ऑब्जेक्ट्स से है, उदाहरण के लिए: "CustomerRepositoryInterface::save()" API फ़ंक्शन हमें "$customer" चर में "CustomerInterface" ऑब्जेक्ट का उपयोग करने की अनुमति देता है, कोड प्रोटोटाइप निम्नलिखित है:

root@kitploit:~
interface CustomerRepositoryInterface
{
/**
 * Create customer.
 */
public function save(\Magento\Customer\Api\Data\CustomerInterface $customer);
}

तो RPC इंटरफ़ेस का उपयोग करके ऑब्जेक्ट कैसे बनाएं? वास्तव में, इस प्रश्न का उत्तर इस बात में निहित है कि Magento SOAP सर्वर को कैसे कॉन्फ़िगर करता है।

Magento SOAP सर्वर का उपयोग करता है जो डिफ़ॉल्ट रूप से PHP के "SoapServer" के साथ बंडल होता है। सही ढंग से कॉन्फ़िगरेशन के लिए, "SoapServer" को एक WSDL फ़ाइल की आवश्यकता होती है, जिसमें सभी विधियाँ, पैरामीटर, तथा वास्तविक RPC अनुरोधों में उपयोग किए जाने वाले कस्टम प्रकार परिभाषित होते हैं। Magento XMLRPC कार्यक्षमता का समर्थन करने वाले प्रत्येक मॉड्यूल के लिए अलग-अलग WSDL फ़ाइलें उत्पन्न करता है, तथा मॉड्यूल की webapi.xml फ़ाइल से मान सीधे निर्धारित करता है।

जब कोई RPC अनुरोध सर्वर द्वारा पार्स किया जाता है, तो सर्वर WSDL फ़ाइल में उपलब्ध डेटा का उपयोग यह निर्धारित करने के लिए करता है कि अनुरोध वैध है या नहीं, तथा अनुरोध की विधि, पैरामीटर और प्रकारों की जाँच करता है। यदि अनुरोध वैध है, तो पार्स किए गए अनुरोध ऑब्जेक्ट को आगे की प्रक्रिया के लिए Magento को भेज दिया जाता है। एक अत्यंत महत्वपूर्ण बिंदु यह है कि "SoapServer" किसी भी तरह से Magento के साथ इंटरैक्ट नहीं करता है; मॉड्यूल की विधियों और पैरामीटरों के बारे में सारी जानकारी WSDL फ़ाइल से आती है। इस बिंदु पर, भेजा गया अनुरोध अभी भी नेस्टेड ऐरे से बना होता है, और SoapServer की पार्सिंग अवस्था में कोई ऑब्जेक्ट नहीं बनाया जाता है। आवश्यक ऑब्जेक्ट बनाने के लिए, Magento इनपुट को स्वयं संसाधित करना जारी रखता है।

पैरामीटर नाम और डेटा प्रकार निकालने के लिए, Magento अनुरोध की विधि से प्रोटोटाइप प्राप्त करता है (पूर्ववर्ती कोड देखें)। कुछ बुनियादी डेटा प्रकारों, जैसे स्ट्रिंग, ऐरे, बूलियन आदि के लिए, सिस्टम इनपुट को संबंधित प्रकार से मैप करेगा। लेकिन ऑब्जेक्ट प्रकारों के लिए, समाधान की प्रक्रिया अधिक जटिल है।

यदि पैरामीटर का डेटा प्रकार किसी वर्ग का उदाहरण (instance) है, तो Magento प्रदान किए गए इनपुट का उपयोग करके उदाहरण बनाने का प्रयास करेगा। ध्यान रखें, इस समय इनपुट केवल एक डिक्शनरी है, जिसकी key गुण (property) का नाम है तथा value गुण का मान है।

सबसे पहले, Magento आवश्यक वर्ग का एक नया उदाहरण बनाएगा। फिर, यह निम्नलिखित विधि का उपयोग करके इसे भरने का प्रयास करेगा:

  1. गुण का नाम प्राप्त करें (इनपुट डिक्शनरी की key से)
  2. "Set[Name]" नामक सार्वजनिक विधि खोजें, जहाँ [Name] गुण का नाम है
  3. यदि ऐसी विधि मौजूद है, तो गुण मान को पैरामीटर के रूप में उपयोग करके उसे निष्पादित करें
  4. यदि ऐसी कोई विधि नहीं है, तो उस गुण को अनदेखा करें और अगले गुण को देखना जारी रखें

Magento इस विधि के अनुसार उन सभी गुणों को संसाधित करेगा जिन्हें उपयोगकर्ता सेट करने का प्रयास कर रहा है। जब सभी गुणों की जाँच हो जाती है, तो Magento यह मान लेगा कि उदाहरण सेट हो चुका है और अगले पैरामीटर को संसाधित करेगा। जब सभी पैरामीटर इस प्रकार संसाधित हो जाते हैं, तो Magento अंततः उस API विधि को निष्पादित करेगा।

संक्षेप में, Magento आपको एक ऑब्जेक्ट बनाने, उसके सार्वजनिक गुणों को सेट करने, और अंततः उसके RPC के माध्यम से "Set" से शुरू होने वाली किसी भी विधि को निष्पादित करने की अनुमति देता है। और यही व्यवहार Magento की भेद्यता को जन्म देता है।

शोध से पता चला कि कुछ API कॉल शॉपिंग कार्ट में विशिष्ट जानकारी सेट करने की अनुमति देते हैं, यह जानकारी हमारा डाक पता, उत्पाद, या यहाँ तक कि हमारी भुगतान विधि भी हो सकती है।

जब Magento शॉपिंग कार्ट उदाहरण में हमारी जानकारी सेट करता है, तो यह नए जोड़े गए डेटा को डेटाबेस में संग्रहीत करने के लिए उदाहरण की "save" विधि का उपयोग करता है।

आइए देखें कि "save" विधि कैसे काम करती है!

root@kitploit:~
/**
* Save object data
*/
public function save(\Magento\Framework\Model\AbstractModel $object)
{
...
// If the object is valid and can be saved
if ($object->isSaveAllowed()) {
    // Serialize whatever fields need serializing
    $this->_serializeFields($object);
    ...
    // If the object already exists in the DB, update it
    if ($this->isObjectNotNew($object)) {
        $this->updateObject($object);
    // Otherwise, create a new record
    } else {
        $this->saveNewObject($object);
    }
     
    // Unserialize the fields we serialized
    $this->unserializeFields($object);
}
...
return $this;
}
// AbstractDb::save()

Magento सुनिश्चित करता है कि हमारे ऑब्जेक्ट मान्य हैं, फिर उन सभी भागों को सीरियलाइज़ करता है जिन्हें सीरियलाइज़ किया जाना चाहिए और उन्हें डेटाबेस में संग्रहीत करता है, तथा अंत में पहले सीरियलाइज़ किए गए भागों को अनसीरियलाइज़ करता है।

सरल लगता है, है ना? वास्तव में ऐसा नहीं है, आइए आगे देखें कि Magento कैसे निर्धारित करता है कि किन भागों को सीरियलाइज़ किया जाना चाहिए।

root@kitploit:~
/**
* Serialize serializable fields of the object
*/
protected function _serializeFields(\Magento\Framework\Model\AbstractModel $object)
{
// Loops through the '_serializableFields' property
// (containing hardcoded fields that should be serialized)
foreach ($this->_serializableFields as $field => $parameters) {
    // Get the field's value
    $value = $object->getData($field);
     
    // If it's an array or an object, serialize it
    if (is_array($value) || is_object($value)) {
        $object->setData($field, serialize($value));
    }
}
}
// AbstractDb::_serializeFields()

जैसा कि हम देखते हैं, केवल वे भाग जो हार्डकोडेड डिक्शनरी "_serializableFields" में मौजूद हैं, सीरियलाइज़ किए जा सकते हैं। सबसे महत्वपूर्ण बात यह है कि यह विधि केवल यह सुनिश्चित करने के बाद ही सीरियलाइज़ेशन जारी रखती है कि field का मान एक ऐरे या ऑब्जेक्ट है।

अब, आइए देखें कि Magento कैसे निर्धारित करता है कि किन भागों को अनसीरियलाइज़ किया जाना चाहिए।

root@kitploit:~
/**
* Unserialize serializeable object fields
*/
public function unserializeFields(\Magento\Framework\Model\AbstractModel $object)
{
// Loops through the '_serializableFields' property
// (containing hardcoded fields that should be serialized)
foreach ($this->_serializableFields as $field => $parameters) {
    // Get the field's value
    $value = $object->getData($field);
     
    // If it's not an array or an object, unserialize it
    if (!is_array($value) && !is_object($value)) {
        $object->setData($field, unserialize($value));
    }
}
}
// AbstractDb::unserializeFields ()

ठीक है, यह बहुत समान दिखता है। एकमात्र अंतर यह है कि इस बार Magento को यह सुनिश्चित करना होगा कि field का मान कोई ऐरे या ऑब्जेक्ट नहीं है। इन 2 जाँचों के कारण, हम एक ऑब्जेक्ट इंजेक्शन हमला करने में सक्षम होने चाहिए, अर्थात एक सीरियलाइज़ेबल field में एक विशिष्ट प्रारूप वाली स्ट्रिंग सेट करना। जब हम इसे इस तरह सेट करते हैं, तो सिस्टम ऑब्जेक्ट को डेटाबेस में संग्रहीत करने से पहले इस field को सीरियलाइज़ नहीं करेगा, क्योंकि यह ऑब्जेक्ट या ऐरे नहीं है। लेकिन, डेटाबेस क्वेरी निष्पादित होने के बाद, जब सिस्टम इसे अनसीरियलाइज़ करने का प्रयास करेगा, तो यह अनसीरियलाइज़ हो जाएगा, क्योंकि यह ऑब्जेक्ट या ऐरे नहीं है।

लेकिन यही छोटी सी, लगभग अदृश्य स्थिति भेद्यता उत्पन्न करती है। शेष प्रश्न यह है कि कौन से field "सीरियलाइज़ेबल" माने जाते हैं, और हम इसे कैसे सेट करते हैं।

निःसंदेह, पहला प्रश्न सरल है, मुझे केवल यह खोजना है कि किस वर्ग में "_serializableFields" गुण है। शीघ्र ही, "Payment" वर्ग में एक API विधि मिली, लेकिन यह पैरामीटर के रूप में नहीं है, इसलिए इसके उदाहरण गुणों को बनाया या नियंत्रित नहीं किया जा सकता। सबसे महत्वपूर्ण बात, इसका सीरियलाइज़ेबल field "additional_information" केवल एक ऐरे के रूप में सेट किया जा सकता है, और एक अतिरिक्त सुरक्षा उपाय के रूप में "Set[PROPERTY_NAME]" तकनीक का उपयोग किया जाता है, इसलिए न केवल इसे बनाया नहीं जा सकता, बल्कि यदि संभव भी हो, तो हम इसे स्ट्रिंग के रूप में सेट नहीं कर सकते।

लेकिन दिलचस्प बात यह है कि इसे एक अलग "चतुर" तरीके से सेट किया जा सकता है। जब Magento पैरामीटर उदाहरण के गुणों को सेट करता है, तो यह वास्तव में गुणों को सेट नहीं करता है, बल्कि उन्हें "_data" नामक एक डिक्शनरी में संग्रहीत करता है। जब किसी उदाहरण के गुणों का उपयोग किया जाता है, तो यह डिक्शनरी उपयोग में आती है। हमारे लिए इसका अर्थ यह है कि हमारा सीरियलाइज़ेबल field - "additional_information" वास्तव में एक सामान्य गुण के बजाय एक आंतरिक डिक्शनरी में संग्रहीत होता है।

इसलिए, यदि हम "_data" डिक्शनरी को पूर्ण रूप से नियंत्रित कर सकते हैं, तो हम आसानी से "additional_information" field की ऐरे सीमा को बायपास कर सकते हैं, क्योंकि हम इसे "Set[PROPERTY_NAME]" को कॉल करने के बजाय मैन्युअल रूप से सेट कर सकते हैं।

लेकिन, हम इस संवेदनशील डिक्शनरी को कैसे नियंत्रित करें?

हमारे "Payment" उदाहरण को सहेजने से पहले, Magento को एक कार्य करना होता है, वह है इसके गुणों को संपादित करना। Magento हमारे API इनपुट को उस भुगतान जानकारी के रूप में मानता है जिसे "Payment" उदाहरण में संग्रहीत किया जाना चाहिए, निम्नानुसार:

root@kitploit:~
/**
* Adds a specified payment method to a specified shopping cart.
*/
public function set($cartId, \Magento\Quote\Api\Data\PaymentInterface $method)
{
 
$quote = $this->quoteRepository->get($cartId); // Get the cart instance
$payment = $quote->getPayment(); // Get the payment instance
// Get the data from the user input
$data = $method->getData();
// Check for additional data
if (isset($data['additional_data'])) {
    $data = array_merge($data, (array)$data['additional_data']);
    unset($data['additional_data']);
}
// Import the user input to the Payment instance
$payment->importData($data);
 
...
}
// PaymentMethodManagement::set()

जैसा कि हम देखते हैं, "Payment" डेटा "$method->getData()" को कॉल करके "$method" पैरामीटर से "_data" गुण लौटाकर प्राप्त किया जाता है। याद रखें, क्योंकि "$method" API विधि का एक पैरामीटर है, हम इसे नियंत्रित कर सकते हैं।

जब Magento हमारे "$method" पैरामीटर पर "getData()" कॉल करता है, तो पैरामीटर की "_data" गुण लौटाई जाती है, जिसमें हमारे द्वारा डाली गई सभी भुगतान जानकारी शामिल होती है। उसके बाद, यह "_data" गुण को इनपुट के रूप में उपयोग करके "importData()" को कॉल करता है, जो "Payment" उदाहरण की "_data" गुण को हमारी "_data" गुण से प्रतिस्थापित कर देता है। इस बिंदु पर, अब हम अपने नियंत्रण वाली "_data" गुण का उपयोग करके "Payment" उदाहरण की संवेदनशील "_data" गुण को प्रतिस्थापित कर सकते हैं, जिसका अर्थ है कि अब हम "additional_information" field सेट कर सकते हैं।

unserialize() को कार्यशील बनाने के लिए, हमें field को स्ट्रिंग के रूप में सेट करने में सक्षम होना चाहिए, लेकिन "Set[PROPERTY_NAME]" विधि केवल ऐरे की अनुमति देती है। समाधान "importData()" को कॉल करने से पूर्व की 2 पंक्तियों में निहित है। Magento डेवलपर्स को अपनी स्वयं की भुगतान विधियाँ जोड़ने, अपना स्वयं का डेटा और जानकारी प्रदान करने की अनुमति देता है। इसे साकार करने के लिए, Magento "additional_data" field का उपयोग करता है। यह field एक ऐसी डिक्शनरी है जिसमें अधिक डेटा वाली भुगतान विधि होती है और यह पूर्ण रूप से उपयोगकर्ता-नियंत्रित होती है। अनुकूलित सामग्री को मूल डेटा का भाग बनाने के लिए, Magento "additional_data" डिक्शनरी को मूल "data" डिक्शनरी के साथ मर्ज करता है, जो वास्तव में "additional_data" डिक्शनरी को "data" डिक्शनरी के सभी मानों को अधिलेखित (overwrite) करने की अनुमति देता है, मूल रूप से इसे पूर्णतः अधिलेखित किया जा सकता है। इसका अर्थ है कि 2 डिक्शनरी के मर्ज होने के बाद, उपयोगकर्ता-नियंत्रित "additional_data" डिक्शनरी अब पैरामीटर की "_data" डिक्शनरी बन जाती है, और "importData()" के कारण, यह "Payment" उदाहरण की संवेदनशील "_data" गुण भी बन जाती है। दूसरे शब्दों में, हमने अब सीरियलाइज़ेबल field "additional_information" को पूर्ण रूप से नियंत्रित कर लिया है, और ऑब्जेक्ट इंजेक्शन हमला कर सकते हैं।

चूँकि हम किसी भी वांछित स्ट्रिंग को अनसीरियलाइज़ कर सकते हैं, अब ऑब्जेक्ट इंजेक्शन हमला करने का समय है।

सबसे पहले, हमें "__wakeup()" या "__destruct()" विधि वाले एक ऑब्जेक्ट की आवश्यकता है, ताकि जब ऑब्जेक्ट को अनसीरियलाइज़ या नष्ट किया जाए तो इसे स्वचालित रूप से कॉल किया जा सके। ऐसा इसलिए है क्योंकि भले ही हम ऑब्जेक्ट के गुणों को नियंत्रित कर सकते हैं, हम इसकी विधियों को कॉल नहीं कर सकते। यही कारण है कि हमें PHP की जादुई विधियों (magic methods) पर निर्भर रहना पड़ता है, जो किसी घटना घटित होने पर स्वचालित रूप से कॉल हो जाती हैं।

हम जिस पहले ऑब्जेक्ट का उपयोग करेंगे, वह "Credis_Client" वर्ग का एक उदाहरण है, जिसमें निम्नलिखित विधियाँ हैं:

root@kitploit:~
/*
* Called automaticlly when the object is destrotyed.
*/
public function __destruct()
{
if ($this->closeOnDestruct) {
    $this->close();
}
}
/*
* Closes the redis stream.
*/
public function close()
{
if ($this->connected && ! $this->persistent) {
        ...
        $result = $this->redis->close();
}
...
}
// Credis_Client::__destruct(), close()

हम देख सकते हैं कि इस वर्ग में एक सरल "__destruct" विधि है (जिसे ऑब्जेक्ट नष्ट होने पर PHP द्वारा स्वचालित रूप से कॉल किया जाता है) जो "close()" विधि को कॉल करती है। दिलचस्प बात यह है कि "close()" विधि, यदि यह पाती है कि Redis सर्वर से एक सक्रिय कनेक्शन है, तो यह उसे बंद करने के लिए "redis" गुण में मौजूद "close()" को कॉल करेगी।

चूँकि "unserialize()" हमें सभी ऑब्जेक्ट गुणों को नियंत्रित करने की अनुमति देता है, हम "redis" गुण को भी नियंत्रित कर सकते हैं। हम गुण में (केवल Redis ही नहीं) कोई भी वांछित ऑब्जेक्ट सेट कर सकते हैं, और सिस्टम के किसी भी वर्ग में किसी भी "close()" विधि को कॉल कर सकते हैं। यह हमारे हमले की सतह को काफी बढ़ा देता है। Magento में कुछ "close()" विधियाँ हैं, और चूँकि ये विधियाँ सामान्यतः स्ट्रीम समाप्त करने, फ़ाइल हैंडल बंद करने तथा ऑब्जेक्ट डेटा संग्रहीत करने के लिए उपयोग होती हैं, हमें कुछ दिलचस्प कॉल मिल जानी चाहिए।

जैसा कि हमने अपेक्षा की थी, हमें "Transaction" वर्ग में निम्नलिखित "close()" विधि मिली:

root@kitploit:~
/**
* Close this transaction
*/
public function close($shouldSave = true)
{
...
if ($shouldSave) {
    $this->save();
}
...
}
/**
* Save object data
*/
public function save()
{
$this->_getResource()->save($this);
return $this;
}
// Magento\Sales\Model\Order\Payment\Transaction::__destruct(), close()

यह सरल दिखता है, "close()" विधि "save()" विधि को कॉल करती है जो आगे "_resource" गुण में "save()" विधि को कॉल करती है। उसी तर्क के अनुसार, चूँकि हम "_resource" गुण को नियंत्रित करते हैं, हम इसके वर्ग को भी नियंत्रित कर सकते हैं, इसलिए हम किसी भी वांछित वर्ग की "save()" विधि को कॉल कर सकते हैं।

यह एक और बड़ा कदम आगे है। जैसा कि हमने अनुमान लगाया था, "save()" विधि सामान्यतः विभिन्न भंडारण माध्यमों (जैसे: फ़ाइल सिस्टम, डेटाबेस आदि) में विभिन्न डेटा सहेजने के लिए उपयोग होती है। अब हमें केवल एक ऐसी "save()" विधि खोजनी है जो भंडारण माध्यम के रूप में फ़ाइल सिस्टम का उपयोग करती है।

शीघ्र ही, मुझे एक मिल गई:

root@kitploit:~
/**
* Try to save configuration cache to file
*/
public function save()
{
...
// save stats
file_put_contents($this->getStatFileName(), $this->getComponents());
...
}
// Magento\Framework\Simplexml\Config\Cache\File::save()

यह विधि वास्तव में "components" field के डेटा को एक फ़ाइल में सहेजती है। चूँकि फ़ाइल का पथ "stat_file_name" field से प्राप्त होता है, और चूँकि हम इन 2 पैरामीटरों को नियंत्रित करते हैं, हम वास्तव में फ़ाइल के पथ और सामग्री को नियंत्रित करते हैं, जिससे एक मनमाना फ़ाइल लेखन (arbitrary file write) भेद्यता उत्पन्न होती है।

अब हमें केवल एक मान्य, लिखने योग्य तथा वेब सर्वर द्वारा सुलभ पथ खोजने पर विचार करना है जहाँ फ़ाइल लिखी जा सके। सभी Magento इंस्टॉलेशन निर्देशिकाओं में एक "/pub" निर्देशिका होती है, जिसका उपयोग छवियों या व्यवस्थापक द्वारा अपलोड की गई फ़ाइलों को संग्रहीत करने के लिए होता है, यह एक प्रभावी ढंग से उपयोग योग्य पथ है।

अंत में हमें केवल सर्वर पर एक PHP वेबशेल फ़ाइल लिखनी है, और हम Magento सर्वर पर बिना प्राधिकरण के मनमाना PHP कोड निष्पादित कर सकते हैं।

0x02 शोषण

परीक्षण वातावरण स्थापित करना

  1. भेद्यता वाला इंस्टॉलेशन पैकेज डाउनलोड करें (यहाँ संस्करण 2.0.0 उपयोग किया गया है) डाउनलोड पता: https://github.com/magento/magento2/archive/2.0.0.zip
  2. Magento इंस्टॉल करें इंस्टॉलेशन चरण: https://github.com/magento/magento2/tree/2.0.0

नोट: यहाँ कुछ समस्याओं का सामना हो सकता है, इन्हें देखें:

  • http://magento2king.com/magento2-insta-be-downloaded/
  • https://github.com/magento/magento2/issues/2419

भेद्यता का शोषण

exploit-db पर सार्वजनिक रूप से उपलब्ध शोषण स्क्रिप्ट (exploit) का डाउनलोड पता: https://www.exploit-db.com/exploits/39838/

शोषण विधि निम्नलिखित है:

  1. भेद्यता वाली Magento वेबसाइट खोजें Magento संस्करण ऑनलाइन जाँच: http://magentoversion.com/

  2. शॉपिंग कार्ट में एक उत्पाद जोड़ें यहाँ छवि का विवरण दर्ज करें

  3. शॉपिंग कार्ट में जाकर "चेकआउट" पर क्लिक करें यहाँ छवि का विवरण दर्ज करें

  4. डाक पता भरें और POST अनुरोध /rest/default/V1/guest-carts/[guestCartId]/shipping-information देखें तथा [guestCartID] प्राप्त करें यहाँ छवि का विवरण दर्ज करें यहाँ छवि का विवरण दर्ज करें

  5. उपरोक्त शोषण स्क्रिप्ट को magento_exp.php के रूप में सहेजें और निष्पादित करें: php magento_exp.php [Magento_URL] [guestCartID] ([webshell लेखन पथ]) यहाँ छवि का विवरण दर्ज करें

बैच जाँच

उपरोक्त शोषण स्क्रिप्ट के शोध से पता चला कि इस शोषण के लिए निम्नलिखित शर्तों को पूरा करना आवश्यक है:

  1. लक्ष्य साइट का Magento संस्करण 2.0.6 से कम होना चाहिए और REST API सक्षम होना चाहिए
  2. लक्ष्य साइट के होमपेज पर निम्नलिखित JS मौजूद होनी चाहिए यहाँ छवि का विवरण दर्ज करें

इसलिए, ऊपर दिए गए शोषण के साथ उपयोग के लिए एक सरल बैच जाँच स्क्रिप्ट लिखी गई:

root@kitploit:~
#!/usr/bin/env python
import urllib
import sys
import socket
timeout = 5
socket.setdefaulttimeout(timeout)

input = sys.argv[1]  #包含Magento站点的URL的文件
output = sys.argv[2] #结果的保存文件,可以为:output.txt

def logFile(str):
    f = open(output,'a')
    f.write(str+"\n")
    f.close()

def checkVul(url):
    try:
	    html = urllib.urlopen(url).read()
	    if "guest-carts" in html:
		    print url,"is vulnerable!"
		    logFile(url)
	    else:
		    print url,"is not vulnerable!"
    except Exception:
	    pass

if __name__ == '__main__':
    inp = open(input,'r')
    for i in inp:
	    url=i.strip()
	    #print url
	    checkVul(url)
    print "All Done!"

निष्पादन परिणाम: यहाँ छवि का विवरण दर्ज करें

0x03 बचाव

Magento को नवीनतम संस्करण (2.0.6) में अपग्रेड करें, डाउनलोड पता: https://www.magentocommerce.com/download

संदर्भ

  • http://netanelrub.in/2016/05/17/magento-unauthenticated-remote-code-execution/

  • https://www.exploit-db.com/exploits/39838/

टूल डाउनलोड करें