准备
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发送请求