某json <= 1.2.68 远程代码执行漏洞分析
2020-06-16 10:56:57 Author: xz.aliyun.com(查看原文) 阅读量:631 收藏

这里主要分析漏洞产生原因和构造方法以及利用的一个思路

最近Fastjson又爆出了可绕过Autotype造成远程代码执行的漏洞,1.2.69版本已经在2020/06/01号发布
对比了一下1.2.68版本与1.2.69版本,发现核心代码其实并没有什么变更,主要是增加了几个黑名单

核心所在其实还是ParserConfig.java中的checkAutoType方法

这里增加了对expectClass类的限制,其中从原来的增加7项增加到了10项,且全部转为16进制的Hash判断,那么多出来的3个这里是暂时是未知的。

在Fastjson中存在AutoType这个东西,目的是为了防止进行恶意反序列化对象从而导致的安全问题,如果在没有启用AutoType的情况下默认是只有白名单以及一些基础类型可以被反序列化。

关于checkAutoType中的expectClass参数,该形参类型为 java.lang.Class
当expectClass参数不为Null、且当前需要实例化的类型是expectClass的子类或实现时会将传入的类视为一个合法的类(此类不能在黑名单中),然后通过TypeUtils.loadClass返回该类型的Class.
至于这个存在的原因应当是例如 com.cyx.A 为白名单, com.cyx.A 的构造方法中或setter中存在 com.cyx.B,那么要想实例化 com.cyx.A 则需要传入 com.cyx.B 对象,而 com.cyx.B 并不在白名单中,所以将其作为expectClass参数传入checkAutoType方法中检测该类是否合法,如果是 com.cyx.B 的子类或实现则视为合法的类。
哪如果攻击者找到了一个白名单类,而构造方法中或setter方法中含有 java.lang.Object 这种祖宗类参数,子类非常多的类型,哪是不是就变相的绕过了AutoType?
关于这一点Fastjson其实有做防范,在checkAutoType方法中判断了expectClass的类型

可以看到如果expectClassFlag不为true的话,最终还是无法加载到类,导致失败

所以到这里应该能大概的了解出这次绕过AutoType的方式了:

  1. 以某个类作为expectClass参数传入checkAutoType
  2. 查找反序列化expectClass的子类或实现,如果构造方法或setter中含有其它类型可重复第一步构造一个反序列化链,直到找到可以利用的类为止

前面已经说到如何去利用,所以这里需要寻找一个子类或实现非常多的类或接口都行,在实际中还是主要看checkAutoType方法中,有哪些对象或接口可以通过校验,实际测试中存在如下几种:

  • 白名单(符合白名单条件的类)
  • TypeUtils.mappings (符合缓存映射中获取的类)
  • typeMapping (ParserConfig中本身带有的集合)
  • deserializers (符合反序列化器的类)

测试中发现实际上 TypeUtils.mappings 中含有相当多的类,其中就包括了接口 java.lang.AutoCloseable

该类型使用的是JavaBeanDeserializer反序列化器,在通过该反序列化器实例化对象时由于该类型为接口,将会继续解析下一个JSON字段,如果存在且为类型,则将 java.lang.AutoCloseable 作为 expectClass 参数传入checkAutoType检测下一个类型是否合法,相关片段代码如下

这里走进checkAutoType,可以看到我第二个字段为类型,值是 com.cyx.Ajava.lang.AutoCloseable的实现)

跟进checkAutoType

那么这里就顺利的绕过了AutoType的检测,获得了一个恶意类型 com.cyx.A,然后通过构造方法造成命令执行

{"@type":"java.lang.AutoCloseable", "@type":"com.cyx.A", "cmd":"calc.exe"}

最后关于 java.lang.AutoCloseable 的实现是非常多的,真实环境下应当从下面寻找,因为一些原因Exploit这里不方便发出


文章来源: http://xz.aliyun.com/t/7878
如有侵权请联系:admin#unsafe.sh