FastJson最新反序列化漏洞分析

isnull   ·   发表于 2019-07-20 11:05:42   ·   漏洞文章

漏洞危害:严重

  • 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


    转自先知社区

    打赏我,让我更有动力~

    0 条回复   |  直到 2019-7-20 | 1264 次浏览
    登录后才可发表内容
    返回顶部 投诉反馈

    © 2016 - 2024 掌控者 All Rights Reserved.