前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >fastjson 1.2.68 反序列化漏洞 gadget 的一种挖掘思路

fastjson 1.2.68 反序列化漏洞 gadget 的一种挖掘思路

原创
作者头像
C4rpeDime
修改2020-06-11 10:11:38
3.3K0
修改2020-06-11 10:11:38
举报
文章被收录于专栏:黑白安全黑白安全

关于漏洞

fastjson 的这个新漏洞在 1.2.68 及之前版本的 autotype 关闭的情况下仍然可以绕过限制反序列化,相比 1.2.47 版本的漏洞来讲这个版本的漏洞还是有一些限制的(关于 1.2.47 漏洞可以参考我的另一篇文章《Java 反序列化漏洞始末(3)— fastjson》[1]),例如 1.2.47 是可以绕过黑名单的限制的,而这个漏洞则无法绕过黑名单,并且需要类实现 AutoCloseable 接口。目前主要的 JNDI gadget 已经进了黑名单,还不允许反序列化类实现了 ClassLoader、DataSource、RowSet 接口,这就导致了绝大部分的 JNDI gadget 无法利用,所以本篇文章主要分享一下 gadget 的挖掘思路和漏洞的原理分析。

漏洞分析

这个漏洞的的成因和我的另一篇文章《fastjson 1.2.68 最新版本有限制 autotype bypass》[2]一致,都是由于期望类(expectClass)导致的,这个漏洞的期望类范围更大,更容易找到具有危害的 gadget。

首先看 DefaultJSONParser#parseObject 这里将 @type 指定的类作为条件去获取 Deserialzer 对象。

ParserConfig#getDeserializer 方法中不满足条件所以到了最后一步通过ParserConfig#createJavaBeanDeserializer 方法来构造 JavaBeanDeserializer

在这一步创建了 JavaBeanDeserializer 对象,而漏洞也就发生在 JavaBeanDeserializer 类中。

现在回到 DefaultJSONParser#parseObject 应该走下一步 JavaBeanDeserializer#deserialze 方法。

用期望类的思路,可以找到此处有两个方法使用了 ParserConfig#checkAutoType 且指定了期望类。

一个是 deserialzeArrayMapping() 另一个是 deserialze()

在 deserialze() 方法中又做了一次 checkAutoType 检测,此处直接将第二个 @type 的类名,和前面构造 JavaBeanDeserializer 对象时指定的期望类直接传了进来。

我在 《fastjson 1.2.68 最新版本有限制 autotype bypass》[2] 这篇文章提到过,当 checkAutoType(String typeName, Class<?> expectClass, int features) 方法的 typeName 实现或继承自 expectClass,就会通过检验。

但还有三个问题,会阻碍 gadget 的触发。

ActionScript

代码语言:javascript
复制
boolean expectClassFlag;
if (expectClass == null) {
    expectClassFlag = false;
} else if (expectClass != Object.class && expectClass != Serializable.class && expectClass != Cloneable.class && expectClass != Closeable.class && expectClass != EventListener.class && expectClass != Iterable.class && expectClass != Collection.class) {
    expectClassFlag = true;
} else {
    expectClassFlag = false;
}

第一个问题是期望类的黑名单,里面包括了大部分常用的父接口和父类,却唯独少了一个 java.lang.AutoCloseable。这也就是为什么 AutoCloseable 为什么可以通过校验的第一个原因,第二个原因是TypeUtils#mappings里有 AutoCloseable 类。

第二个问题是黑名单类,fastjson 在 denyHashCodes 里几乎把常见的容易造成漏洞的类都加进了黑名单,这就造成了攻击成本变高,如果要利用漏洞,只能花费更多的时间去寻未被发现的常用库 gadget。

第三个问题是父类、父接口黑名单,fastjson 在判断期望类之前将继承自 ClassLoader、DataSource、RowSet 的类直接抛出异常。

ActionScript

代码语言:javascript
复制
if (ClassLoader.class.isAssignableFrom(clazz) || DataSource.class.isAssignableFrom(clazz) || RowSet.class.isAssignableFrom(clazz)) {
    throw new JSONException("autoType is not support. " + typeName);
}

而常用的 JNDI RCE 类基本上都继承自 DataSource 和 RowSet,所以能找到的 JNDI gadget 基本都无法在这个漏洞中使用。

以上三点足够让大部分常见的 gadget 无法使用,所以需要换一种 gadget 挖掘思路。

gadget

关于 gadget 的挖掘思路我主要是寻找关于输入输出流的类来写文件,IntputStream 和 OutputStream 都是实现自 AutoCloseable 接口的,而且也没有被列入黑名单,所以只要找到合适的类,还是可以进行文件读写等高危操作的。

JNDI

前面说到,这个漏洞基本无法使用 JNDI,实际上并不完全是,当 fastjson 小于 1.2.51 时,还是可以通过实现了 RowSet 接口的类进行 JNDI 反序列化,但实际上已经没有什么危害,大多数都更新到了 1.2.60+ 版本。

文件读写

我寻找 gadget 时的条件是这样的。

•需要一个通过 set 方法或构造方法指定文件路径的 OutputStream•需要一个通过 set 方法或构造方法传入字节数据的 OutputStream,并且可以通过 set 方法或构造方法传入一个 OutputStream,最后可以通过 write 方法将传入的字节码 write 到传入的 OutputStream•需要一个通过 set 方法或构造方法传入一个 OutputStream,并且可以通过调用 toString、hashCode、get、set、构造方法调用传入的 OutputStream 的 flush 方法

以上三个组合在一起就能构造成一个写文件的利用链,最终我挑选出了三个符合条件的类作为演示。

漏洞复现

漏洞的原理摸清了,接下来我将用本地的模拟环境复现一遍漏洞。

写文件

复制文件

总结

本文旨在给安全研究者提供一种反序列化漏洞 gadget 挖掘思路,文中 POC 代码暂不公开。

修复方案

•更新到 1.2.69 或更高版本•未能更新到 1.2.69 版本的请将 AutoCloseable、OutputStram、InputStream、RowSet 列入反序列化黑名单

References

[1] 《Java 反序列化漏洞始末(3)— fastjson》: https://b1ue.cn/archives/184.html [2] 《fastjson 1.2.68 最新版本有限制 autotype bypass》: https://b1ue.cn/archives/348.html

文由微信公众号安全档案

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 关于漏洞
  • 漏洞分析
  • gadget
  • JNDI
  • 文件读写
  • 漏洞复现
  • 写文件
  • 复制文件
  • 总结
  • 修复方案
    • References
    相关产品与服务
    文件存储
    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档