
Un analizzatore di bytecode per trovare catene di gadget di deserializzazione in applicazioni Java
Questo progetto ispeziona librerie Java e classpath alla ricerca di catene di gadget. Le catene di gadget sono utilizzate per costruire exploit per vulnerabilità di deserializzazione. Scoprendo automaticamente possibili catene di gadget nel classpath di un'applicazione, i penetration tester possono costruire rapidamente exploit e gli ingegneri della sicurezza delle applicazioni possono valutare l'impatto di una vulnerabilità di deserializzazione e dare priorità alla sua correzione.
Questo progetto è stato presentato al Black Hat USA 2018. Scopri di più lì! (Link in sospeso)
DISCLAIMER: Questo progetto è al massimo alpha. Ha bisogno di test e documentazione aggiunti. Sentiti libero di aiutare aggiungendo entrambi!
Supponendo che tu abbia un JDK installato sul tuo sistema, dovresti essere in grado di eseguire semplicemente ./gradlew shadowJar. Puoi quindi eseguire l'applicazione con java -jar build/libs/gadget-inspector-all.jar <args>.
Questa applicazione si aspetta come argomento(i) un percorso a un file war (nel qual caso il war verrà esploso e tutte le sue classi e librerie utilizzate come classpath) oppure un qualsiasi numero di jar.
Nota che l'analisi può essere intensiva in termini di memoria (e finora gadget inspector non è stato ottimizzato per essere meno avido di memoria). Per librerie piccole probabilmente vorrai allocare almeno 2GB di dimensione dell'heap (cioè con il flag -Xmx2G). Per applicazioni più grandi vorrai usare quanta più memoria puoi.
Il kit di strumenti passerà attraverso diverse fasi di ispezione del classpath per costruire dataset per l'uso nelle fasi successive. Questi dataset sono scritti in file con estensione .dat e possono essere scartati dopo l'esecuzione (sono scritti principalmente in modo che le fasi precedenti possano essere saltate durante lo sviluppo).
Dopo che l'analisi è stata eseguita, verrà scritto il file gadget-chains.txt.
Il seguente è un esempio dall'esecuzione contro commons-collections-3.2.1.jar, ad esempio con
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 c'è la seguente catena:
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)
Il punto di ingresso di questa catena è un'implementazione della classe JDK InvocationHandler. Usando lo stesso trucco della catena di gadget originale di commons-collections, qualsiasi implementazione serializzabile di questa classe è raggiungibile in una catena di gadget, quindi la catena scoperta inizia qui. Questo metodo invoca classToInvocationHandler.get(). La catena di gadget scoperta indica che classToInvocationHandler può essere serializzato come un DefaultedMap in modo che questa invocazione salti a DefaultedMap.get(). Il passo successivo nella catena invoca value.transform() da questo metodo. Il parametro value in questa classe può essere serializzato come un InvokerTransformer. All'interno del metodo transform di questa classe vediamo che chiamiamo cls.getMethodName(iMethodName, ...).invoke(...). Gadget inspector ha determinato che iMethodName è controllabile dall'attaccante come membro serializzato, e quindi un attaccante può eseguire un metodo arbitrario sulla classe.
Questa catena di gadget è il blocco fondamentale della catena completa di gadget di commons-collections scoperta da Frohoff. Nel caso sopra, gadget inspector ha scoperto l'ingresso attraverso CompositeInvocationHandlerImpl e DefaultedMap invece di AnnotationInvocationHandler e LazyMap, ma è sostanzialmente la stessa.
Se stai cercando altri esempi del tipo di catene che questo strumento può trovare, le seguenti librerie hanno anche alcuni risultati interessanti:
Non dimenticare che puoi anche puntare gadget inspector a un'applicazione completa (impacchettata come JAR o WAR). Per esempio, analizzando il war per l'applicazione Zksample2 otteniamo la seguente catena di gadget:
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)
Come puoi vedere, questo utilizza diverse librerie contenute nell'applicazione per costruire la catena.
D: Se gadget inspector trova una catena di gadget, si può costruire un exploit da essa?
R: Non sempre. L'analisi utilizza alcune ipotesi semplificative e può segnalare falsi positivi (catene di gadget che in realtà non esistono). Come semplice esempio, non cerca di risolvere la soddisfacibilità delle condizioni di ramificazione. Pertanto segnalerà quanto segue come una catena di gadget:
public class MySerializableClass implements Serializable {
public void readObject(ObjectInputStream ois) {
if (false) System.exit(0);
ois.defaultReadObject();
}
}
Inoltre, gadget inspector ha condizioni piuttosto ampie su quelle funzioni che considera interessanti. Per esempio, tratta la reflection come interessante (cioè chiamate a Method.invoke() dove un attaccante può controllare il metodo), ma spesso asserzioni trascurate significano che un attaccante può influenzare il metodo invocato ma non ha il controllo completo. Per esempio, un attaccante può essere in grado di invocare il metodo "getError()" in qualsiasi classe, ma non qualsiasi altro nome di metodo.
D: Se non sono state trovate catene di gadget, significa che la mia applicazione è al sicuro da sfruttamento?
R: No! Per prima cosa, gadget inspector ha un insieme molto ristretto di funzioni "sink" che considera avere effetti collaterali "interessanti". Questo certamente non significa che non ci siano altri comportamenti interessanti o pericolosi non presenti nell'elenco.
Inoltre, ci sono una serie di limitazioni dell'analisi statica che fanno sì che gadget inspector avrà sempre punti ciechi. Come esempio, gadget inspector attualmente non rileverebbe questo perché non segue le chiamate di reflection.
public class MySerializableClass implements Serializable {
public void readObject(ObjectInputStream ois) {
System.class.getMethod("exit", int.class).invoke(null, 0);
}
}