URLDNS链
前言
URLDNS链是ysoserial中的一条利用链,通常是用来检测是否存在Java反序列化漏洞,是一条比较简单的利用链,具有以下特点:
- URLDNS链只能发起DNS请求,不能进行其他利用
- 不限制jdk版本,但是使用java内置类,对第三方依赖没有要求
- 目标无回显,可以通过DNS请求来验证是否存在反序列化漏洞
URLDNS链分析
URL类继承了java.io.Serializable,可以进行序列化

调用openConnection方法
v
会返回URLConnection

URLConnection为一个抽象类,它的实现类通常是HttpURLConnection,但是到最后会无法进行序列化,同时因为openConnection同名函数很少,因此无法调用。所以一般不用这个函数。

来看另一个比较常见的函数hashCode,在hashCode函数中调用了handle的getHostAddress()

hashCode的默认值(初始值)为-1

首先判断值是否为-1,如果不是-1,则直接返回缓存值hashCode,无法执行handler.hashCode函数,也就不会触发getHostAddress函数,所以在下面反序列化时不会发起DNS查询
1 | |
进入handler的hashCode可以看到又调用了getHostAddress(),getHostAddress()会把URL里的hostname转换成IP地址,这个过程就会触发DNS解析

继续进入getHostAddress()函数,可以看到InetAddress.getByName这里可以触发DNS请求

所以只要可以调用到URL类中的的hashCode()函数,就可以发起DNS请求,验证是否存在反序列化漏洞
在HashMap中的readObject()函数中可以看到调用了hash()函数

继续跟进hash()函数,就可以看到其中调用了key的hashCode()函数,可以看到Object key,就是key是实例化后的一个对象,追溯到之前说到得到url.hashcode就是相当于把URL实例化为对象,对象名为key,这样就是一个URLDNS链的调用

所以进行构造,入口类为HashMap类,执行类就是URL类,两个类中都存在相同名称类型的hashCode()方法
在URL构造参数里可以知道直接传入一个URL网址就好,这里做测试就可以用BP的协作器(Collaborator)生成一个域名,最后序列化hashmap即可
构造代码

这里用到的域名就是在BP的协作器(Collaborator)生成的一个,先进行序列化创建文件,代码运行之后可以去BP看一下”立即轮询“,这个时候正常是没有结果的,因为这里只进行了序列化,没有进行反序列化,所以没有触发DNS解析。

执行反序列化之后,再次轮询就可以看到结果了

再来看到代码,这里可以跟进put函数

就会发现在put中就会调用到hash方法

进而调用到hashcode()发起DNS请求

继续来回顾到代码,这里就是用到了反射来改变已有的对象属性,将hashCode的值改为-1,吻合了上面对URL类中的hashCode的分析:
首先判断值是否为
-1,如果不是-1,则直接返回缓存值hashCode,无法执行handler.hashCode函数,也就不会触发getHostAddress函数,所以在下面反序列化时不会发起DNS查询

在执行完hashMap.put(url,1);之后变成了输入的URL的hashCode,这里可以通过在put函数这句下断点调试看到,此时的hashcode不是-1,因此在执行这句代码时不发起DNS请求,在执行完这句代码之后、序列化之前,将hashCode改为-1,从而可以在反序列化时发起DNS请求。

完整代码
1 | |
反序列化时,在判断条件处下断点调试,可以看到此时hashCode值为-1

总结
这个链子首先就是从HashMap的readObejct的HashMap.hash中的Object.hashCode进入,调用了URL.hashCode中的URLStreamHandler中的URLStreamHandler.getHostAddress的InetAddress.getByName触发DNS请求。
- 入口类:HashMap类:从
HashMap的readObejct的HashMap.hash中的Object.hashCode进入 - 调用类:调用
URL.hashCode中的URLStreamHandler中的URLStreamHandler.getHostAddress的InetAddress.getByName触发DNS请求 - 相同名称类型的函数:
hashCode HashMap可以接收Object对象,所以可以将URL类的实例化对象也就是key传入HashMap中,最终在HashMap中调用的不是Object.hashCode,而是URLStreamHandler.hashCode

URLDNS整体调用链
- HashMap.readObject()
- HashMap.hash()
- URL.hashCode()
- URLStreamHandler.hashCode()
- URLStreamHandler.getHostAddress()
- URLStreamHandler.InetAddress.getByName()