0x 前言
最近碰到几个关于java 反序列化的问题,很多时候都会利用 ysoserial 这个工具来生成payload,于是这次决定来跟一跟 ysoserial 里面最简单的 URLDNS 这条利用链
0x 准备分析
先看看 ysoserial 生成 URLDNS 的这段代码:
注释里说得很明白,利用链是:
* Gadget Chain:
* HashMap.readObject()
* HashMap.putVal()
* HashMap.hash()
* URL.hashCode()
所以我们就从 HashMap 中的 readObject 入手
首先 ,下载 ysoserial.jar ,然后生成payload:
java -jar ysoserial.jar URLDNS http://***.ceye.io >out.bin
测试代码:
import java.io.ObjectInputStream;
import java.io.FileInputStream;
public class URLDNS {
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("out.bin"));
ois.readObject();
}
}
使用 ceye 平台来记录 dns 查询
0x 调试过程
根据调用链,首先在java.util.HashMap#readObject 里面的putVal下断点:
接着进入 java.util.HashMap#hash 里面:
run 几次后,看到 key = http://***.cecy.io
跟进,来到 java.net.URL#hashCode
跟进来到 java.net.URLStreamHandler#hashCode:
跟进 getHostAddress:
这里 getByName 函数 就会去进行一个 dns 查询。
平台成功收到 dns 查询:
0x 后记
(1)总的来说,利用原理就是,当 hashmap 的key 在 put 以及 get 的时候,会计算key 的 hash ,而如果这个key 是 url 类型的时候,都会调用 java.net.URL#hashCode 方法来计算,在hashCode() 方法中,如果hashCode 不为-1 ,就会调用 java.net.URLStreamHandler#hashCode 方法,而这个方法里面就正好会进行 dns 查询。
(2)URLDNS 这个利用链主要用来检测是否存在反序列化漏洞,有如下两个优点:
i. 使用java 内部的类进行构造,不依赖第三方库
ii. 如果目标可以出网,在目标没有回显的时候,可以用来验证是否存在反序列化漏洞。
(3)另外,还有一些生成payload 的细节,可以看 ysoserial 生成URLDNS 的源码,比如:
i .在用 SilentURLStreamHandler 继承URLStreamHandler,重写了里面的getHostAddress() 方法来避免在生成payload 的时候进行 dns 查询。
ii. 将 url put 到hashmap 中之后,重新设置hashCode 为 -1 ,这样在反序列化的时候就会再重新计算hashCode 。