准备
URLDNS链是反序列化中比较简单的一个链,它不受第三方依赖和版本的限制,所以通常用来判断是否存在反序列化。
ysoserialize项目地址:https://github.com/frohoff/ysoserial
先用ysoserial测试是否可用

然后readObject()触发

成功在DNSlog接收到请求

分析URLDNS链
首先漏洞触发点是在HashMap的readObject()
对传入序列化数据流进行反序列化

可以看到在putVal()中对key进行了Hash()处理

再进入到URL.hashCode()
handler属性默认是URLStreamHandler类

在URLStreamHandler.hashCode()中直接调用getHostAddress(),getByName()会对url参数进行解析操作,从而发起一次dnslog请求。


利用链到此为止
1 | HashMap -> readObject() |
但是注意到在生成payload时候对HashMap进行了Put操作,而put函数里也有putVal处理

所以在生成payload时候也发送了dnslog请求,我们得规避这种情况。
在上面可以看到URL.hashCode()中有个判断,如果hashCode不等于-1那就直接return

所以可以利用反射来在put之前修改它的值,再之后又修改回-1
poc:
1 | import java.io.FileInputStream; |
Ysoserial中的URLDNS
首先在pom.xml找到入口类

在解释器中添加运行时参数

这样即可在项目中运行调试Poc

在URLDNS链部分与上面分析的没出入,但是注意到ysoserialize.URLDNS并没有通过反射来防止在生成payload时触发getHostAdress()

而是在SilentURLStreamHandler()这个类中重写了getHostAddress(),这样在put过程中遇到getHostAddress()就直接返回Null了,不会发送请求。

那为什么在readObject时又能进入到正确的getHostAddress()呢
是URL.handler是transient声明的,无法被序列化,所以在反序列化时依然能向dnslog发送请求


