又遇fastjson漏洞

简介: 又是fastjson!又是这家伙!至少经历了2次+这样的场景。我不知道这家伙又得罪了哪位大仙,频繁被“黑”。fastjson到底做错了什么?为什么会被频繁爆出漏洞?但是作为一个技术人(兴趣爱好者),我更关注的是它为什么会频繁被爆漏洞?而其他的Gson却没有。通过对fastjson的releaseNote以及部分源代码进行查阅,发现此现象跟fastjson中的一个AutoType特性有关联。

     又是fastjson!又是这家伙!至少经历了2次+这样的场景。我不知道这家伙又得罪了哪位大仙,频繁被“黑”。fastjson到底做错了什么?为什么会被频繁爆出漏洞?但是作为一个技术人(兴趣爱好者),我更关注的是它为什么会频繁被爆漏洞?而其他的Gson却没有。通过对fastjson的releaseNote以及部分源代码进行查阅,发现此现象跟fastjson中的一个AutoType特性有关联

    Java处理Json数据有三个比较流行的类库,Gson(google维护)、Jackson、以及今天的

主角Fastjson。

     fastjson是阿里巴巴一个开源的json相关的java library,地址:https://github.com/alibaba/fastjson,Fastjson可以将java的对象转换成json的形式,也可以用来将json转换成Java对象,效率较高,被广泛的用在web服务以及android上,它的JSONString()方法可以将Java的对象转换成json格式,同样通过parseObject方法可以将json数据转换成java的对象。这个阿里巴巴的开源一个牛逼的Json解析库,通常被用于将Java Bean和Json字符串之间进行转换。

     这次被工信部通报公司系统存在漏洞,导致了公司各业务线升级fastjson版本,以防止系统安全问题。对部分业务包进行查看,发现当前使用的fastjson版本不一,不过都是在1.2.68之前版本。2020年真是不平凡的一年,fastjson组件库频繁暴露安全漏洞,此漏洞可以绕过autoType开关来实现反序列化远程代码执行并获取服务器访问权限。

     从2019年7月份发布的v1.2.59一直到2020年6月份发布的 v1.2.71 ,每个版本的升级中都有关于AutoType的升级,涉及13个正式版本。fastjson中与AutoType相关的版本历史可参考如下:


1.2.59发布,增强AutoType打开时的安全性 fastjson
1.2.60发布,增加了AutoType黑名单,修复拒绝服务安全问题 fastjson
1.2.61发布,增加AutoType安全黑名单 fastjson
1.2.62发布,增加AutoType黑名单、增强日期反序列化和JSONPath fastjson
1.2.66发布,Bug修复安全加固,并且做安全加固,补充了AutoType黑名单 fastjson
1.2.67发布,Bug修复安全加固,补充了AutoType黑名单 fastjson
1.2.68发布,支持GEOJSON,补充了AutoType黑名单
1.2.69发布,修复新发现高危AutoType开关绕过安全漏洞,补充了AutoType黑名单
1.2.70发布,提升兼容性,补充了AutoType黑名单
1.2.71发布,补充安全黑名单,无新增利用,预防性补充

     关于1.2.68版本的漏洞中,其主要利用方式是利用异常进行攻击,并且重写getMessage方法。其实本质最广泛的是使用AutoCloseable这个接口绕过checkAutoType,网上大多也以这种方式展开分析。因为AutoCloseable构成的payload所需要的条件可能没有那么复杂。之前有文章中说1.2.69已经修复了异常攻击漏洞,但是经过测试似乎并没有。

     然而,截止到2020年11月份发布的v1.2.75版本,依然没有对异常类进行处理,所以仍然存在漏洞,该漏洞的利用条件如下:


      1、危险类必须继承“系统白名单”中任意一个异常类

      2、危险类中的危险方法必须为构造方法或者setter方法,参数可控是最好的。

      以fastjson1.2.68为例,当初产生的主要原因在于,fastjson为了再次避免用户用其AutoType机制进行反序列化而产生漏洞,加入了checkAutoType方法,AutoType机制的标志就是“@type”这个标签。checkAutoType这个方法本意是不想让用户使用AutoType,除非用户自己开启AutoType。然而在checkAutoType方法实现过程中还是没忍住偷偷用了几下(标志是解析了"@type"标志),但加强了限制。在代码审计过程中,我发现,在com.alibaba.fastjson.parser.ParserConfig第1326行


clazz = TypeUtils.getClassFromMapping(typeName);

     其中typeName变量是用户输入的序列化之后的JSON格式数据中,含有类名的字符串,比如{"@type","com.demo.test"}这个json数据,其typeName就是com.demo.test。这行代码的意思就是从TypeUtils这个类中尝试获取json中提到的类。在TypeUtils的静态方法中,执行了addBaseClassMappings函数,其函数代码如下(注意其中含有AutoCloseable接口):


private static void addBaseClassMappings(){
        mappings.put("byte", byte.class);
        mappings.put("short", short.class);
        mappings.put("int", int.class);
        mappings.put("long", long.class);
        mappings.put("float", float.class);
        mappings.put("double", double.class);
        mappings.put("boolean", boolean.class);
        mappings.put("char", char.class);
        mappings.put("[byte", byte[].class);
        mappings.put("[short", short[].class);
        mappings.put("[int", int[].class);
        mappings.put("[long", long[].class);
        mappings.put("[float", float[].class);
        mappings.put("[double", double[].class);
        mappings.put("[boolean", boolean[].class);
        mappings.put("[char", char[].class);
        mappings.put("[B", byte[].class);
        mappings.put("[S", short[].class);
        mappings.put("[I", int[].class);
        mappings.put("[J", long[].class);
        mappings.put("[F", float[].class);
        mappings.put("[D", double[].class);
        mappings.put("[C", char[].class);
        mappings.put("[Z", boolean[].class);
        Class<?>[] classes = new Class[]{
                Object.class,
                java.lang.Cloneable.class,
                loadClass("java.lang.AutoCloseable"),
                java.lang.Exception.class,
                java.lang.RuntimeException.class,
                java.lang.IllegalAccessError.class,
                java.lang.IllegalAccessException.class,
                java.lang.IllegalArgumentException.class,
                java.lang.IllegalMonitorStateException.class,
                java.lang.IllegalStateException.class,
                java.lang.IllegalThreadStateException.class,
                java.lang.IndexOutOfBoundsException.class,
                java.lang.InstantiationError.class,
                java.lang.InstantiationException.class,
                java.lang.InternalError.class,
                java.lang.InterruptedException.class,
                java.lang.LinkageError.class,
                java.lang.NegativeArraySizeException.class,
                java.lang.NoClassDefFoundError.class,
                java.lang.NoSuchFieldError.class,
                java.lang.NoSuchFieldException.class,
                java.lang.NoSuchMethodError.class,
                java.lang.NoSuchMethodException.class,
                java.lang.NullPointerException.class,
                java.lang.NumberFormatException.class,
                java.lang.OutOfMemoryError.class,
                java.lang.SecurityException.class,
                java.lang.StackOverflowError.class,
                java.lang.StringIndexOutOfBoundsException.class,
                java.lang.TypeNotPresentException.class,
                java.lang.VerifyError.class,
                java.lang.StackTraceElement.class,
                java.util.HashMap.class,
                java.util.Hashtable.class,
                java.util.TreeMap.class,
                java.util.IdentityHashMap.class,
                java.util.WeakHashMap.class,
                java.util.LinkedHashMap.class,
                java.util.HashSet.class,
                java.util.LinkedHashSet.class,
                java.util.TreeSet.class,
                java.util.ArrayList.class,
                java.util.concurrent.TimeUnit.class,
                java.util.concurrent.ConcurrentHashMap.class,
                java.util.concurrent.atomic.AtomicInteger.class,
                java.util.concurrent.atomic.AtomicLong.class,
                java.util.Collections.EMPTY_MAP.getClass(),
                java.lang.Boolean.class,
                java.lang.Character.class,
                java.lang.Byte.class,
                java.lang.Short.class,
                java.lang.Integer.class,
                java.lang.Long.class,
                java.lang.Float.class,
                java.lang.Double.class,
                java.lang.Number.class,
                java.lang.String.class,
                java.math.BigDecimal.class,
                java.math.BigInteger.class,
                java.util.BitSet.class,
                java.util.Calendar.class,
                java.util.Date.class,
                java.util.Locale.class,
                java.util.UUID.class,
                java.sql.Time.class,
                java.sql.Date.class,
                java.sql.Timestamp.class,
                java.text.SimpleDateFormat.class,
                com.alibaba.fastjson.JSONObject.class,
                com.alibaba.fastjson.JSONPObject.class,
                com.alibaba.fastjson.JSONArray.class,
        };
        for(Class clazz : classes){
            if(clazz == null){
                continue;
            }
            mappings.put(clazz.getName(), clazz);
        }
    }


     可以发现是系统将这些类加入了mappings中,之前提到的方法显而易见了,即尝试在TypeUtils类中获取typeName值,如果没有获取到,那么clazz为null,若expectClass此时也为null,就会触发异常,告诉用户AutoType不可用。正常情况下AutoType就是被禁止了。然而还有另一种情况,若clazz不为空,则就存在绕过限制的可能,绕过的关键就是TypeUtils.mappings中所包含的类,它们就相当于是“系统的白名单”。

      更详细的:

      1、fastjson会首先从左至右寻找JSON格式中带“@type”的键,若存在,则将其键对应的值(即typeName)通过checkAutoType方法检查是否在"系统的白名单中"和用户自定义的白名单中,当然系统还有自带的黑名单,typeName还不能在黑名单中。

      以下为1.2.68系统设定的黑名单:


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 = false;
            } else {
                expectClassFlag = true;
            }
        }

       2、在确定typeName不在黑名单而又在白名单后,会将typeName赋值为expectClass,expectClass可是个好东西啊,相当于一个强大的通行证,他会允许expectClass的儿子们(实现类或子类)不需要通过系统白名单检查直接通过。1.2.68漏洞也因这个“通行证”而产生。

     关于3者Json框架的特性的相关情况,简要如下:

Fastjson

1、速度快
fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能一直高于其他类型库
2、使用简单
fastjson的API十分简洁。
3、使用广泛
fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。

Jackson

1、容易使用 - jackson API提供了一个高层次外观,以简化常用的用例。
2、无需创建映射 - API提供了默认的映射大部分对象序列化。
3、性能高 - 快速,低内存占用,适合大型对象图表或系统。
4、干净的JSON - jackson创建一个干净和紧凑的JSON结果,这是让人很容易阅读。
5、不依赖 - 库不需要任何其他的库,除了JDK。


Gson

1、输出轻量易读的JSON。
2、支持任意复杂的对象。
3、允许自定义对象的表现形式。
4、允许预先存在的不可变的对象转换为JSON或与之相反。
5、提供一种机制,使得将Java对象转换为JSON或相反如使用toString()以及构造器(工厂方法)一样简单。

     相比之下,其他的json框架,如Gson和Jackson,漏洞数量少很多,高危漏洞也比较少。并且,其他2种框架也在努力改进中,各自有各自的优势,从中远期来看,若fastjson漏洞一直无法修复或者避免,Gson未尝不是一个性价比更高的选择呢?


相关文章
|
JSON fastjson Java
FastJson、JackJson 以及 Gson 的区别
FastJson、JackJson 以及 Gson 是 Java 生态圈中三种常用的 Json 解析器,它们均可将 Java 对象序列化为 Json 格式的字符串,也可将 Json 字符串反序列化为 Java 对象。下面我们讨论一下三者在序列化和反序列化操作中的一些区别。
1379 0
|
存储 缓存 算法
数据库必知词汇:布隆过滤器(Bloom Filter)
布隆过滤器(Bloom Filter)是由Burton Bloom 在1970年提出的,其后在P2P上得到了广泛的应用。一个空的布隆过滤器是一个m位的位数组,所有位的值都为0。定义了k个不同的符合均匀随机分布的哈希函数,每个函数把集合元素映射到位数组的m位中的某一位。Bloom filter算法可用来查询某一数据是否在某一数据集合中。其优点是查询效率高、可节省空间。但其缺点是会存在一定的错误。因此Bloom filter 算法仅仅能应用于那些同意有一定错误的场合。可使用Bloom filter 算法的场合包含字典软件、分布式缓存、P2P网络和资源路由等等。
1557 0
|
传感器 人工智能 监控
智慧化工厂AI算法方案
智慧化工厂AI算法方案针对化工行业生产过程中的安全风险、效率瓶颈、环保压力和数据管理不足等问题,通过深度学习、大数据分析等技术,实现生产过程的实时监控与优化、设备故障预测与维护、安全预警与应急响应、环保监测与治理优化,全面提升工厂的智能化水平和管理效能。
1503 0
智慧化工厂AI算法方案
|
4月前
|
供应链 测试技术 开发者
用 Docker 轻松部署 ERPNext 15:多场景实战指南
ERPNext 15 是一款功能全面的开源企业资源规划系统,结合 Docker 容器化部署,具备高效、灵活、低成本等优势。适用于小微企业数字化起步、多分支机构协同办公、开发者测试环境搭建、短期项目管理及企业内部培训等多种场景。模块化设计支持按需扩展,满足不同规模企业需求,是实现高效企业管理的理想选择。
用 Docker 轻松部署 ERPNext 15:多场景实战指南
|
5月前
|
NoSQL MongoDB 开发者
Python与MongoDB的亲密接触:从入门到实战的代码指南
本文详细介绍了Python与MongoDB结合使用的实战技巧,涵盖环境搭建、连接管理、CRUD操作、高级查询、索引优化、事务处理及性能调优等内容。通过15个代码片段,从基础到进阶逐步解析,帮助开发者掌握这对黄金组合的核心技能。内容包括文档结构设计、批量操作优化、聚合管道应用等实用场景,适合希望高效处理非结构化数据的开发者学习参考。
305 0
|
安全 API 开发者
国内Claude 3.5怎么注册使用?
Claude 3.5由Anthropic开发,可通过特定平台如Slack或API使用。注册需用稳定邮箱如Gmail,并通过国外手机号验证。Slack用户可直接添加Claude 3.5应用进行交互,支持中英文。开发者可注册Anthropic API获取密钥。此外,国内有镜像服务可供使用。请注意隐私政策及访问限制。
1424 2
国内Claude 3.5怎么注册使用?
|
数据采集 机器学习/深度学习 自然语言处理
一文讲懂大模型调优技术
随着AI技术的发展,大模型如GPT系列、BERT等成为推动自然语言处理和计算机视觉领域进步的重要驱动力。然而,大模型的调优过程复杂且资源消耗巨大,对开发者构成严峻挑战。本文旨在全面解析大模型调优的关键技术,涵盖数据预处理、模型架构调整、超参数优化、正则化与泛化能力提升,以及分布式训练与并行优化等内容,为开发者提供系统性的调优指南。
|
前端开发 流计算
程序与技术分享:css样式大全,完整的Css样式大全(整理)
程序与技术分享:css样式大全,完整的Css样式大全(整理)
262 1
|
存储 物联网 数据安全/隐私保护
如何让AppleWatch自动锁定Mac?
我们都知道AppleWatch支持了解锁Mac的功能,如果您的 Mac(2013 年中或后续机型)安装了macOS Sierra(Apple Watch Series 1 和 Apple Watch Series 2)、macOS High Sierra 或更高版本(Apple Watch Series 3 或后续机型),那么当其从睡眠模式唤醒时,Apple Watch 会立即解锁您的 Mac。
1659 1
如何让AppleWatch自动锁定Mac?
|
存储 中间件 API
fastadmin框架token验证
fastadmin框架token验证
703 0