FastJson最新反序列化漏洞分析
2019-07-17 10:01:00 Author: xz.aliyun.com(查看原文) 阅读量:126 收藏

漏洞危害:严重

  • FastJson最新爆出的绕过方法可以通杀1.2.48版本以下所有,有传言在autotype开启的情况下可以打到1.2.57。
    ## 解决方案:
  • FastJson升级到最新1.2.58版本;
  • 采用默认的关闭autotype
    ## 漏洞详情:
    fastjson是alibaba开源的一款高性能功能完善的JSON库,在2017年4月18日的时候官方自己爆出了一个安全漏洞,https://github.com/alibaba/fastjson/wiki/security_update_20170315,影响范围 1.2.24以及之前版本。随着逐步修复,1.2.42-45之间都出现过绕过。而最近爆出的更是通杀默认配置1.2.48版本以下。下边是漏洞分析。

payload:

这次绕过的大体思路是通过java.lang.Class,将JdbcRowSetImpl类加载到map缓存,从而绕过autotype的检测。因此将payload分两次发送,第一次加载,第二次执行。默认情况下,只要遇到没有加载到缓存的类,checkautotype就会抛出异常并中止。

入口在parse方法,单步进去

一步步跟到DefaultJSONParser.java中有一段调用checkautotype,也就是检测的核心逻辑。跟进该方法

clazz = this.config.checkAutoType(typeName, (Class)null, lexer.getFeatures())

在开启的情况下,checkautotype方法类似黑名单,会进入下图逻辑,通过将类名hash后和denyHashCodes进行对比。目前有人fuzz出了部分黑名单中的类:https://github.com/LeadroyaL/fastjson-blacklist。
开启的情况下,当黑名单检测命中时,根据代码逻辑,会先通过loadClass方法加载该类并返回,因此就绕过了检测。

在autotype关闭的情况下,checkautotype方法类似白名单,主要检测类是否在白名单中,也就是是否被加载。通过getClassFromMapping尝试在缓存加载该类。如果不存在,下边还会通过deserializers来找,如果都没有,下边就会抛异常。

当发送第一次请求时,Class是通过deserializers.findClass加载的,然后Class将JdbcRowSetImpl类加载进map中,然后第二次请求时,就这里就成功找到了JdbcRowSetImpl类,从而绕过检测。

加载JdbcRowSetImpl后,就和之前的payload一样了,通过JdbcRowSetImpl中的调用链,通过jndi的lookup加载远程类。

调用栈如下图

JavaBeanDeserializer.deserialze -> FieldDeserializer.setValue -> 通过反射调用setAutoCommit方法给属性赋值 -> JNDI connect,connect里调用InitialContext的lookup方法,根据前面payload里设置的DataSourceName找到,然后请求我们的jndi server下载远程类并执行构造函数,从而造成rce。当然在8u191之上,需要结合tomcat el或者ldap来绕过。8u191之下可以通过ldap reference来绕过对rmi从远程的Codebase加载Reference工厂类的限制。
JNDI注入高版本绕过参考:https://kingx.me/Restrictions-and-Bypass-of-JNDI-Manipulations-RCE.html

48中的修复措施是,在loadClass时,将缓存开关默认置为false,所以默认是不能通过Class加载进缓存的。同时将Class类加入到了黑名单中。

最后附上jndi server


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