`
mwei83
  • 浏览: 1325 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

fastjson1.2.24漏洞分析及源码分析

    博客分类:
  • java
阅读更多

近期出现fastjson的远程代码执行漏洞,fastjson国内知名度很高的json库,趁这个机会学习下,与大家分享下漏洞原因,fastjson反序列化流程。
远程代码执行漏洞

反序列原理
1 通过入参类型,生成反序列化器。
2 反序列化器调用入参类型的无参构造函数,创建对象。

3 解析序列化字符串,取出Key,Value值,调用相应的setKey(Value)方法。
这个漏洞主要是fastjson的一个 autotype 功能。下面代码是一个简单例子。

public class MyTest4AutoType {
    public static String userStr2="{\"@type\":\"com.mogujie.zhaoyun.mytest.User\",\"age\":12,\"birthday\":1493295579866,\"name\":\"myname\"}";

    public static void main(String[] args){
        User user2 = (User) JSON.parse(userStr2);
        System.err.println(user2.getName());
    }
}


这面是fastjson的一个黑科技,json字符串里增加一个特殊K,V值。key 固定为@type,value为此json字符串要反序列化的类全路径。这样就能通过入参,控制json字符串反序列化生成的对象。
下面这块就是fastjson(1.2.24)的代码

                if (key == JSON.DEFAULT_TYPE_KEY && !lexer.isEnabled(Feature.DisableSpecialKeyDetect)) {
                    String typeName = lexer.scanSymbol(symbolTable, '"');
                    Class<?> clazz = TypeUtils.loadClass(typeName, config.getDefaultClassLoader());

                    if (clazz == null) {
                        object.put(JSON.DEFAULT_TYPE_KEY, typeName);
                        continue;
                    }



Class<?> clazz = TypeUtils.loadClass(typeName, config.getDefaultClassLoader());typeName就是入参的类的全路径
上面的方法就是获得这个自定义类,安全漏洞就在这里。原因就是,这个方法没做任何类名的安全校验,也没有白名单机制。
通过前面反序列化原理知道,应用会执行自定义类的set方法赋值。loadClass这个方法没做任何过滤,也就是说可以传入任何jvm加载过的类,并执行setKey方法,Key也是传入的,可变的。
剩下的就是寻找符合以下条件的类:
1,JVM加载过的类;
2,有非静态set方法;
3,入参只有一个。
假如寻找到赋值后改变的是类变量的Class,那就能肆意妄为了。
上面的demo稍加改动,就变成下面的了,虽然后抛出异常,但是ClassLoader.setDefaultAssertionStatus仍然后执行。

public class MyTest4AutoType {
        public static String userStr2="{\"@type\":\"com.alibaba.fastjson.util.ASMClassLoader\",\"defaultAssertionStatus\":true}";
    public static void main(String[] args){
        User user2 = (User) JSON.parse(userStr2);
        System.err.println(user2.getName());
    }
}


1.2.24之后的版本都修复了这个漏洞,如果代码不做任何修改,自定义类的反序列化都会失败。解决方案就是增加白名单配置,例如 ParserConfig.global.addAccept("com.alibaba"),所有以com.alibaba开始的类都能反序列化了。fastjson还有黑名单配置功能,例如 ParserConfig.global.addDeny("javax.swing"),所有javax.swing开始的类都不反序列化。无论黑名单还是白名单,都是全局配置,可以统一控制fastjson。

反序列化解析


反序列化核心方法:com.alibaba.fastjson.JSON#parseObject(java.lang.String, java.lang.reflect.Type, com.alibaba.fastjson.parser.ParserConfig, com.alibaba.fastjson.parser.deserializer.ParseProcess, int, com.alibaba.fastjson.parser.Feature...);我们以这个方法为入口开始观察反序列化过程。

 

1,DefaultJSONParser parser = new DefaultJSONParser(input, config,featureValues);

DefaultJSONParser 是反序列化的核心类,是外观模式,包括配置(ParserConfig)、反序列化实现(ObjectDeserializer)、词法解析(JSONLexer)等功能组合在一起,依赖关系可以看下上面的类图。

DefaultJSONParser通过json字符串(input),反序列化全局配置(config),反序列化实例特征配置(featureValues)。这个实例创建好后,反序列化的基础就准备好了。

ParserConfig 全局唯一的反序列化配置,包括反序列化黑名单(denyList),反序列化白名单(acceptList),是否启用asm(asmEnable),反序列化实现类缓存集合(deserializers),常见关键字缓存(SymbolTable)。这个对象是单例的,包括两大部分:系统默认和自定义。asmEnable就是系统默认,程序加载时候会判断系统是否符合启动ams条件,并赋值。acceptList是自定义的,可以根据不同的业务系统配置不同的白名单。

 

2,T value = (T) parser.parseObject(clazz, null);

这行是反序列化的执行方法,反序列化所有的代码都在这里,分析几个关键代码。

 

2-1,ObjectDeserializer derializer = config.getDeserializer(type);

这个方法是根据入参类型获得反序列化器,每一个基本类型都有一个对应的反序列化器,如NumberDeserializer等,这些都会初始化并储存到deserializers里。自定义类会利用asm或反射生成,并存储到deserializers里,第二次相同的类型反序列化就不会重复创建,直接从deserializers获得。这种设计有两个优势,一是空间换时间,所有反序列化器都缓存起来。二是每一种类型都对应一种反序列化器,代码清晰,优化更有针对性。

 

2-2,ASMDeserializerFactory.createJavaBeanDeserializer(ParserConfig config, JavaBeanInfo beanInfo);

这个方法就是根据入参类型利用asm生成反序列化器,作者直接将asm核心代码迁移到fastjon里,所以fastjson不需要额外依赖asm库。

    使用ASM条件:

  • 非Android系统
  • 该类及其除Object之外的所有父类为是public的
  • 泛型参数非空
  • 非asmFactory加载器之外的加载器加载的类
  • 非接口类
  • 类的setter函数不大于200
  • 类有默认构造函数
  • 类不能含有仅有getter的filed
  • 类不能含有非public的field
  • 类不能含有非静态的成员类
  • 类本身不是非静态的成员类
假如不满足以上条件,fastjson会使用反射生成反序列化器:JavaBeanDeserializer(ParserConfig config, Class<?> clazz, Type type),性能低。
2-3,derializer.deserialze(this, type, fieldName);
反序列化生成对象。json字符串解析器,包括 JSONLexer,JSONLexerBase,JSONReaderScanner,JSONScanner,JSONToken。这块是反序列化性能优化的重点,fastjson中token是用于标识当前在解析过程中解析到的对象的一个标记,具体的值参考 JSONToken。这块使用了基于预测的优化算法,这块就是利用JSON的标准结构猜测字符会是什么样,提高判断效率。如:key的token后最有可能是":",":"之后可能是value的token或为"{"的token或为"["的token等等,从而可以根据前一个token预判下一个token的可能,减少重复判断。

3,return (T) value; 

 

整个反序列化流程就结束了,大家有兴趣的可以自己看看,有很多细节值得大家发现。

 

序列化解析

序列化类图


 
 

反序列化核心方法:com.alibaba.fastjson.JSON#toJSONString(java.lang.Object, com.alibaba.fastjson.serializer.SerializeConfig, com.alibaba.fastjson.serializer.SerializeFilter[], java.lang.String, int, com.alibaba.fastjson.serializer.SerializerFeature...);我们以这个方法为入口开始观察序列化过程,这块因为很多和反序列化的处理方法,设计都是一样的,整体简单描述下。

1,SerializeWriter out = new SerializeWriter(null, defaultFeatures, features);

SerializeWriter继承Writer,能够完成高性能的字符串拼接,相比StringBuilder做了适合json字符串拼装的优化。out初始化包括:申请序列化字符串存储空间(buf),这个空间是申请后是不释放的,放在Threadlocal,避免重复申请带来的性能损耗。序列化特征配置features,包括默认的配置和实例自定义配置,如利用符号(')替代符号("),禁止循环引用,是否输出值为null的字段等,详细的可以看下com.alibaba.fastjson.serializer.SerializerFeature。这块fastjson是用按位或计算的。

2,JSONSerializer serializer = new JSONSerializer(out, config);

JSONSerializer是序列化的核心类,是外观模式,包括配置(SerializeConfig)、序列化实现(ObjectSerializer)、序列化输出(SerializeWriter)、过滤器(SerializeFilterable)等功能组合在一起,依赖关系可以看下上面的类图。 

SerializeConfig是全局唯一的,和ParserConfig功能结构基本一样。它继承自IdentityHashMap,IdentityHashMap是一个长度默认为1024的Hash桶,每个桶存放相同Hash的Entry(可看做链表节点,包含key、value、next指针、hash值)做成的单向链表,IdentityHashMap实现了HashMap的功能,但能避免HashMap并发时的死循环。  

serializers,存储的序列化器,设计和deserializers是一致的。

SerializeFilterable列表,可视为在生成json串的各阶段、各地方定制序列化,大致如下:

 

  • BeforeFilter :序列化时在最前面添加内容
  • AfterFilter :序列化时在最后面添加内容
  • PropertyFilter :根据PropertyName和PropertyValue来判断是否序列化
  • ValueFilter :修改Value
  • NameFilter :修改key
  • PropertyPreFilter :根据PropertyName判断是否序列化

SerialContex 序列化上下文,在引用或循环引用中使用,该值会放入references的Hash桶(IdentityHashMap)缓存。

3,serializer.write(object);

这行是序列化的执行方法,列出几个关键代码。

3-1,ObjectSerializer writer = getObjectWriter(clazz);

这个方法是根据入参类型获得序列化器,整体和反序列化器的生成一致,很多代码结构都是一样的。

3-2,writer.write(this, object, null, null, 0);

每个类型的序列化器都会实现com.alibaba.fastjson.serializer.ObjectSerializer#write。各自实现自己的拼装json字符串逻辑

4,out.toString();

返回json字符串。

 

 参照:http://www.csdn.net/article/2014-09-25/2821866

 

  • 大小: 101.1 KB
  • 大小: 124.3 KB
分享到:
评论

相关推荐

    fastjson1.2.24含源码

    Fastjson 1.2.24版本是其发展过程中的一个重要里程碑,该版本包含了完整的源码,允许开发者深入研究其内部机制,优化自己的代码,或对库进行自定义扩展。 1. **Fastjson简介** Fastjson的核心功能是将Java对象转换...

    fastjson1.2.24反序列化RCE

    **Fastjson 1.2.24 反序列化远程代码执行漏洞详解** 在Java开发中,Fastjson是一个广泛使用的高性能JSON库,它提供了一种快速解析和生成JSON的机制。然而,像许多处理序列化和反序列化的库一样,Fastjson在某些版本...

    fastjson-1.2.24

    在Fastjson 1.2.24版本中,针对之前的安全漏洞进行了修复,增强了其安全性。开发者应定期更新Fastjson以确保应用的安全性。 7. 性能优化 Fastjson在设计时充分考虑了性能,如使用直接操作字节码的技术来提升速度,...

    fastjson-1.2.24.jar

    java运行依赖jar包

    高版本的fastjson-1.2.71解决安全漏洞.rar

    然而,随着广泛使用,Fastjson在早期版本中出现了一些安全漏洞,这些漏洞可能导致远程代码执行(RCE)和其他安全风险。在标题提到的“高版本的fastjson-1.2.71解决安全漏洞”中,我们主要关注的是Fastjson如何通过...

    fastjson2 最新源码

    fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码fastjson2 最新源码...

    fastjson-1.2.83 针对近期阿里fastjson包漏洞,升级解决

    Fastjson 1.2.80 及之前版本使用黑白名单用于防御反序列化漏洞,经研究该防御策略在特定条件下可绕过默认 autoType 关闭限制,攻击远程服务器,风险影响较大。建议 Fastjson 用户尽快采取安全措施保障系统安全

    fastjson 1.2.6 jar包及源码

    源码部分是Fastjson库的实现细节,包含了解析器、生成器、类型转换器等核心组件的源代码。通过阅读源码,开发者可以深入理解其工作原理,对于进行二次开发或排查问题非常有帮助。此外,源码还可以帮助开发者学习和...

    fastjson1.2.40 jar包及源码

    Fastjson是一个Java库,可用于将Java对象转换为其JSON表示形式。 它也可以用来将JSON字符串转换为等效的Java对象。 Fastjson可以使用任意的Java对象,包括你没有源代码的预先存在的对象。

    FastJson 漏洞.md

    Fastjson因其实现简洁高效,在众多项目中被广泛采纳,尤其是在Web应用及Android客户端开发中。 #### 二、Fastjson漏洞概述 Fastjson在多个版本中存在安全漏洞,主要集中在反序列化过程中,这些漏洞可能允许远程...

    java FASTJSON 解析复杂JSON实例源码

    Java中的Fastjson是一个高效、功能丰富的JSON库,由阿里巴巴开发并维护。它提供了一种简单的方式来序列化和反序列化Java对象,使得处理JSON数据变得轻而易举。在这个实例中,我们将深入探讨如何使用Fastjson来解析...

    fastjson的jar包以及源码包 绿色版1.2.41

    二、Fastjson 1.2.41源码分析 1. **解析引擎** 源码中,Fastjson的核心解析引擎使用了高效的扫描器和解析器,通过一次遍历完成JSON字符串到Java对象的转换。深入理解这部分源码有助于提升性能调优能力。 2. **...

    FastjsonScan.jar 用于burp插件,扫描Fastjson漏洞

    burp插件

    fastjson1.2.8 jar包及其源码下载(附带Gson jar包)

    阿里巴巴公司研发的fastjson1.2.8的jar包 以及源码包,是目前开源json解析包中速度最快的工具包,但其在复杂的bean类转json的时候存在一定的问题,所以搭配Gson解析一起。 给各位童鞋一个查找jar包的方式:...

    fastjson漏洞环境

    **Fastjson 漏洞详解** Fastjson 是阿里巴巴开源的一款高性能的 Java JSON 库,它提供了将 Java 对象转换为 JSON 字符串以及从 JSON 字符串反序列化为 Java 对象的功能。然而,自其发布以来,Fastjson 一直存在一些...

    fastJson开发包、源码及相关api文档

    `fastjson-1.1.33-sources.jar`是FastJson的源码,对于学习和调试非常有帮助;`fastjson-1.1.33.jar`则是FastJson的运行库,包含了所有需要的类和方法。 总结来说,FastJson是一个功能强大且高效的JSON处理工具,...

    fastjson1.2.47远程代码漏洞解决方案.rar

    《Fastjson 1.2.47 远程代码执行漏洞详解及修复策略》 Fastjson,一个由阿里巴巴开发的高性能、轻量级的Java语言JSON处理库,因其高效的解析速度和广泛的功能,在国内的互联网行业中被广泛应用。然而,任何优秀的...

Global site tag (gtag.js) - Google Analytics