
Ein Bytecode-Analyzer zum Auffinden von Deserialisierungs-Gadget-Chains in Java-Anwendungen.
Dieses Projekt untersucht Java-Bibliotheken und Classpaths auf Gadget-Chains. Gadget-Chains werden verwendet, um Exploits für Deserialisierungsschwachstellen zu konstruieren. Durch die automatische Erkennung möglicher Gadget-Chains im Classpath einer Anwendung können Penetrationstester schnell Exploits erstellen und Anwendungssicherheitsingenieure die Auswirkungen einer Deserialisierungsschwachstelle bewerten und deren Behebung priorisieren.
Dieses Projekt wurde auf der Black Hat USA 2018 vorgestellt. Erfahren Sie dort mehr dazu! (Links ausstehend)
HINWEIS: Dieses Projekt ist bestenfalls im Alpha-Stadium. Es benötigt Tests und Dokumentation. Helfen Sie gerne mit, indem Sie beides hinzufügen!
Vorausgesetzt, Sie haben ein JDK auf Ihrem System installiert, sollten Sie einfach ./gradlew shadowJar ausführen können. Danach können Sie die Anwendung mit java -jar build/libs/gadget-inspector-all.jar <args> starten.
Diese Anwendung erwartet als Argument(e) entweder einen Pfad zu einer WAR-Datei (in diesem Fall wird die WAR-Datei entpackt und alle ihre Klassen und Bibliotheken als Classpath verwendet) oder eine beliebige Anzahl von JARs.
Beachten Sie, dass die Analyse speicherintensiv sein kann (und Gadget Inspector wurde bisher nicht optimiert, um weniger speicherhungrig zu sein). Für kleine Bibliotheken sollten Sie mindestens 2 GB Heap-Größe zuweisen (z.B. mit dem Flag -Xmx2G). Für größere Anwendungen sollten Sie so viel Speicher wie möglich verwenden.
Das Toolkit durchläuft mehrere Phasen der Classpath-Inspektion, um Datensätze für spätere Phasen aufzubauen. Diese Datensätze werden in Dateien mit der Endung .dat geschrieben und können nach Ihrer Ausführung verworfen werden (sie werden hauptsächlich geschrieben, damit frühere Phasen während der Entwicklung übersprungen werden können).
Nach Abschluss der Analyse wird die Datei gadget-chains.txt geschrieben.
Das Folgende ist ein Beispiel aus der Ausführung gegen commons-collections-3.2.1.jar, z.B. mit
wget http://central.maven.org/maven2/commons-collections/commons-collections/3.2.1/commons-collections-3.2.1.jar
java -Xmx2G -jar build/libs/gadget-inspector-all.jar commons-collections-3.2.1.jar
In gadget-chains.txt findet sich folgende Chain:
com/sun/corba/se/spi/orbutil/proxy/CompositeInvocationHandlerImpl.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object; (-1)
com/sun/corba/se/spi/orbutil/proxy/CompositeInvocationHandlerImpl.invoke(Ljava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object; (0)
org/apache/commons/collections/map/DefaultedMap.get(Ljava/lang/Object;)Ljava/lang/Object; (0)
org/apache/commons/collections/functors/InvokerTransformer.transform(Ljava/lang/Object;)Ljava/lang/Object; (0)
java/lang/reflect/Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (0)
Der Einstiegspunkt dieser Chain ist eine Implementierung der JDK-Klasse InvocationHandler. Mit dem gleichen Trick wie in der ursprünglichen Commons-Collections-Gadget-Chain ist jede serialisierbare Implementierung dieser Klasse in einer Gadget-Chain erreichbar, sodass die entdeckte Chain hier beginnt. Diese Methode ruft classToInvocationHandler.get() auf. Die entdeckte Gadget-Chain zeigt an, dass classToInvocationHandler als DefaultedMap serialisiert werden kann, sodass dieser Aufruf zu DefaultedMap.get() springt. Der nächste Schritt in der Chain ruft value.transform() von dieser Methode aus auf. Der Parameter value in dieser Klasse kann als InvokerTransformer serialisiert werden. In der transform-Methode dieser Klasse sehen wir, dass cls.getMethodName(iMethodName, ...).invoke(...) aufgerufen wird. Gadget Inspector hat festgestellt, dass iMethodName als serialisiertes Mitglied vom Angreifer kontrolliert werden kann, und somit kann ein Angreifer eine beliebige Methode auf der Klasse ausführen.
Diese Gadget-Chain ist der Baustein der von Frohoff entdeckten vollständigen Commons-Collections-Gadget-Chain. Im obigen Fall fand Gadget Inspector zufällig einen Einstieg über CompositeInvocationHandlerImpl und DefaultedMap anstelle von AnnotationInvocationHandler und LazyMap, ist aber im Wesentlichen gleich.
Wenn Sie nach weiteren Beispielen suchen, welche Art von Chains dieses Tool finden kann, enthalten die folgenden Bibliotheken ebenfalls einige interessante Ergebnisse:
Vergessen Sie nicht, dass Sie Gadget Inspector auch auf eine vollständige Anwendung (als JAR oder WAR verpackt) anwenden können. Zum Beispiel erhalten wir bei der Analyse der WAR-Datei der Zksample2-Anwendung die folgende Gadget-Chain:
net/sf/jasperreports/charts/design/JRDesignPieDataset.readObject(Ljava/io/ObjectInputStream;)V (1)
org/apache/commons/collections/FastArrayList.add(Ljava/lang/Object;)Z (0)
java/util/ArrayList.clone()Ljava/lang/Object; (0)
org/jfree/data/KeyToGroupMap.clone()Ljava/lang/Object; (0)
org/jfree/data/KeyToGroupMap.clone(Ljava/lang/Object;)Ljava/lang/Object; (0)
java/lang/reflect/Method.invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object; (0)
Wie Sie sehen, werden dabei verschiedene Bibliotheken aus der Anwendung genutzt, um die Chain aufzubauen.
F: Wenn Gadget Inspector eine Gadget-Chain findet, kann daraus ein Exploit gebaut werden?
A: Nicht immer. Die Analyse verwendet einige vereinfachende Annahmen und kann falsch positive Ergebnisse melden (Gadget-Chains, die nicht wirklich existieren). Ein einfaches Beispiel: Es versucht nicht, die Erfüllbarkeit von Verzweigungsbedingungen zu lösen. Daher wird Folgendes als Gadget-Chain gemeldet:
public class MySerializableClass implements Serializable {
public void readObject(ObjectInputStream ois) {
if (false) System.exit(0);
ois.defaultReadObject();
}
}
Darüber hinaus hat Gadget Inspector recht weitreichende Bedingungen für die Funktionen, die es als interessant betrachtet. Beispielsweise behandelt es Reflektion als interessant (d.h. Aufrufe von Method.invoke(), bei denen ein Angreifer die Methode kontrollieren kann), aber oft übersehen Behauptungen bedeuten, dass ein Angreifer die aufgerufene Methode beeinflussen kann, aber keine vollständige Kontrolle hat. Beispielsweise kann ein Angreifer möglicherweise die Methode "getError()" in jeder Klasse aufrufen, aber keinen anderen Methodennamen.
F: Wenn keine Gadget-Chains gefunden wurden, bedeutet das, dass meine Anwendung vor Ausnutzung sicher ist?
A: Nein! Zum einen hat Gadget Inspector einen sehr engen Satz von "Sink"-Funktionen, die er als "interessant" für Nebenwirkungen betrachtet. Das bedeutet sicherlich nicht, dass es keine anderen interessanten oder gefährlichen Verhaltensweisen gibt, die nicht in der Liste enthalten sind.
Darüber hinaus gibt es eine Reihe von Einschränkungen der statischen Analyse, die dazu führen, dass Gadget Inspector immer blinde Flecken haben wird. Als Beispiel: Gadget Inspector würde dies derzeit übersehen, weil es keine Reflektionsaufrufe verfolgt.
public class MySerializableClass implements Serializable {
public void readObject(ObjectInputStream ois) {
System.class.getMethod("exit", int.class).invoke(null, 0);
}
}