1.前言
URLDNS
利用链是反序列化中较为简单的一条,但利用效果是只能触发一次dns请求,而不能去执行命令。比较适用于漏洞验证这一块,而且URLDNS这条利用链并不依赖于第三方的类,而是JDK中内置的一些类和方法。
在一些漏洞利用没有回显的时候,我们也可以使用到该链来验证漏洞是否存在
2.ysoserial分析
使用ysoserial
来进行分析,将项目导入IDEA
中,下载pom.xml
依赖,寻找程序入口
GeneratePayload
的main方法
首先判段是否传入了两个参数,如果不是则打印帮助信息;是的话会依次分别赋值给payloadType
和command
变量。
之后实例化了一个需要继承ObjectPayload类的类实例化对象,跟进一下getPayloadClass
方法,在ysoserial.payloads.ObjectPayload.Utils
下
先反射生成一个class对象,之后获取包名和类名并加上我们之前传入的payloadType
参数并将返回值赋值给GeneratePayload的payloadclass
根据payloadclass
实例化一个对象赋值给payload,之后调用getObject
方法,跟进
该方法定义于ObjectPayload接口,继续跟进
可以看到该方法在36个利用链中都得到实现,这里进入URLDNS链看看
URLDNS类是实现了ObjectPayload接口,那么上面的操作就是根据输入的参数,获取类名并定位到该类中,也就是进入到利用链的类文件中,调用该类的getObject
方法生成payload并将返回值(也就是序列化payload)赋值给object对象,继续回到GeneratePayload#main
方法中
之后调用serialize()方法将payload序列化并打印输出。
payload生成流程就是这样,下面跟进去运行测试一下,生成一个URLDNS链的序列化payload,这里需要先设置一下参数
设置后直接运行
乱码数据就是上面分析过的,经过一系列操作生成的URLDNS序列化之后的payload字节序列
3.URLDNS链
URLDNS利用链是反序列化中较为简单的一条,但利用效果是只能触发一次dns请求,而不能去执行命令。比较适用于漏洞验证这一块,而且URLDNS这条利用链并不依赖于第三方的类,而是JDK中内置的一些类和方法。
在一些漏洞利用没有回显的时候,我们也可以使用到该链来验证漏洞是否存在
触发点在put
方法,我们在put
方法处打一个断点,在Edit configurations
中设置好参数,debug mainclass文件即可
可以看到ht对象的类HashMap
实现了序列化接口,是可以反序列化的
在此类中搜一下readObject
方法,发现在最后调用了putVal
方法进行了一个hash
计算
回到断点处跟进一下put
方法,参数的key
和value
都是我们输入的dnslog地址
进入put方法,可以看到调用了putVal
方法,也就是readObject方法中的putVal
方法
继续跟进,看一下hash
方法
这里调用key
的hashCode
方法,回到urldns
这个payload
HashMap ht = new HashMap(); // HashMap that will contain the URL
URL u = new URL(null, url, handler); // URL to use as the Key
ht.put(u, url);
可知这里压入的key是一个java.net.URL
对象
跟到java.net.URL的hashCode
方法
这里的hashCode
字段如果为-1,调用handler的hashCode
方法,因此payload中通过反射设置了hashCode的值为-1
此处handler为java.net.URLStreamHandler
的自定义子类SilentURLStreamHandler
对象
跟到java.net.URLStreamHandler
中的hashCode
方法
第10行调用getHostAddress
,继续跟进该方法
这里第10行调用了InetAddress.getByName
,也就是一次dns查询
这里的参数u也就是payload中需要我们传入的参数String url。
而payload中的handler使用自定义的java.net.URLStreamHandle
r的子类SilentURLStreamHandler
对象,原因是
- URLStreamHandler是抽象类不能直接实例化
- 是该子类重写了getHostAddress方法,可避免在生成payload时就触发dns请求。
调用堆栈如下
getHostAddress:84, URLDNS$SilentURLStreamHandler (ysoserial.payloads)
hashCode:359, URLStreamHandler (java.net)
hashCode:885, URL (java.net)
hash:339, HashMap (java.util)
put:612, HashMap (java.util)
getObject:57, URLDNS (ysoserial.payloads)
main:34, GeneratePayload (ysoserial)
在URLDNS里面其实导致反序列化的根本原因是因为Hashmap重写了readobject反序列化方法,而重写后的readobject方法调用了putVal导致的一个利用链
参考文章:
Ysoserial利用链分析 - Escape-w - 博客园 (cnblogs.com)
Ysoserial URLDNS链分析 - Zh1z3ven - 博客园 (cnblogs.com)
Ysoserial URLDNS分析 - Y4er的博客