ysoserial工具分析
一、URLDNS链
当我们运行以下命令时,ysoserial
工具就会给我们构造好URLDNS
链,我们将该字节流反序列化后,就能在dnslog平台看到对应的dns查询记录,那ysoserial
是如何构造这个链的呢?
1 | java -jar ysoserial.jar URLDNS "http://ybrsa4.dnslog.cn" > urldns.txt |
我们从github中下载frohoff/ysoserial源码,并找到URLDNS.java
类,首先可以看到该链的构造概述
我们仔细分析一下源码,了解其构造原理:
其getObject
方法内首先先实例化了一个SilentURLStreamHandler
类,该类属于ysoserial
工具继承URLStreamHandler
类并重写了getHostAddress
和openConnection
方法
主要目的是为了防止该链在序列化之前就触发了DNS查询,导致分不清楚是在构造链还是在反序列化的时候触发的DNS查询。我们继续跟进HashMap
中的put
方法,可以看到其中又调用了putVal
方法,这不就是上面讲到URLDNS
要构造的链吗?
点进hash
方法(跟进的源码在左图,右图为URL类的hashCode
方法),可以看到该方法会调用HashMap
对象key的hashCode
方法,而URL
类的hashCode
方法中,当hashCode
属性为-1
时,会调用handler
对象的hashCode
方法。
在
ysoserial
代码实现中,作者为了防止目标服务器的JDK包中的hashCode
属性不是-1
,特意又将其设置为-1
,不过在JDK17
以及之后默认情况下无法对私有属性进行修改。
我们继续跟进hashCode
方法,可以看到它调用了getHostAddress
,即会发起DNS请求查询其IP地址
前面的代码中,
handler
对象在实例化URL类时,传入了一个URLStreamHandler
类,也就是所说的handler
对象,其重写了getHostAddress
方法,使其不做任何操作,这样也就避免了该对象链在序列化前就触发了DNS请求。
其实以上也差不多是整个链的代码,在目标服务器反序列化的时候,会先调用HashMap
的readObject
方法,我们不妨可以看看HashMap
的此方法,实际上也就是上面分析的流程。