Fastjson 漏洞· 06 · 防御、审计与检测

免责声明:本系列与靶场均具备真实 RCE 能力,仅限本人自建实验环境学习与防御研究,严禁对未授权系统使用。

这一篇分三层:代码怎么根治、上线怎么审计、出事怎么发现与处置。本篇自洽。


引子:一个安全从业者的"日常三问"

前面五篇都是"进攻视角":怎么找 gadget、怎么绕 checkAutoType、怎么把一条日志/JSON 变成 shell。但在真实岗位(甲方、应急、审计、开发安全)上,更常站在防守视角,被反复问三件事:

  1. "系统有没有这个洞?"------需要扫依赖、看版本、翻代码;

  2. "怎么修才彻底?"------需要分清"根治"和"缓解",而不是只会加 WAF;

  3. "出事怎么发现、怎么处置?"------需要设计检测规则、会看日志、能走应急流程。

本篇把 Fastjson 防御拆成三层:代码层根治、审计层方法、检测与应急层落地,并给出一张"措施---性质---是否根治"的对照表,把零散的 payload 知识转化成可交付的防御能力。

同样的思路可以平移到 Log4j2 系列------这就是组件漏洞学习的通用套路。

本篇要点(读完应能回答):

  1. 为什么"用固定目标类型解析"能从根上阻止 autoType 攻击?

  2. 审计时除了 grep JSON.parse,还要看哪两样东西才能判断"是否真的可利用"?

  3. 日志里大量出现 autoType is not support 意味着什么?怎么处置?

  4. WAF / 出网管控 / 升级 JDK 分别处在防御的哪一层?为什么都不能替代根因修复?


一、根治:别让不可信输入决定"加载哪个类"

回顾整个系列的根因:@type 让输入决定要实例化的类。 所以最有效的防御就一句话:

凡是用户可控的数据,都不允许它通过 autoType 去决定类名。

具体做法,按推荐程度从高到低:

1. 用"指定目标类型"的解析,而不是 JSON.parse

复制代码
// 危险:目标类型未知,@type 生效
Object o = JSON.parse(userInput);
​
// 安全:明确目标类型;@type 与目标类型不符会被拒
User u = JSON.parseObject(userInput, User.class);

只要目标类型是固定的 DTO,攻击者就算塞 @type 也实例化不了危险类。这是性价比最高的一条。

2. 关闭 autoType / 开启 safeMode

复制代码
// 明确关闭(1.2.25+ 默认就是 false,但要防止被人打开)
ParserConfig.getGlobalInstance().setAutoTypeSupport(false);
​
// 1.2.68+:彻底关闭 autoType,黑白名单都不看
ParserConfig.getGlobalInstance().setSafeMode(true);
// 或启动参数:-Dfastjson.parser.safeMode=true

注意检查启动脚本/中间件配置里有没有人加过 -Dfastjson.parser.autoTypeSupport=true------这类"为了兼容"的开关是重灾区。

3. 必须用多态时,用"最小白名单"

复制代码
// 好:只允许自己的具体包/类
ParserConfig.getGlobalInstance().addAccept("com.mycompany.api.dto.");
​
// 差(等于没防):宽泛前缀
// addAccept("com.");
// addAccept("java.");

以上 ParserConfig.getGlobalInstance().setAutoTypeSupport(false) / setSafeMode(true) / addAccept(...) 的逐词含义(类、方法、参数分别是什么)见 02 篇的「逐词拆解」。

4. 升级 / 迁移

  • 1.x:升到 1.2.83+;

  • 更优:迁到 fastjson2 (默认安全模型不同)或 Jackson,并关闭多态反序列化。

5. 纵深防御(不能替代上面)

  • 出网管控:限制应用服务器对外的 LDAP/RMI 访问,能挡住大量 JNDI 类链;

  • JDK 保持较新,不要加 trustURLCodebase=true;

  • WAF/网关做关键词与结构检测(见下),但已知可以绕过,只作辅助。


二、代码审计:拿这几条去搜

审计 Java 项目时,围绕"用户输入 + Fastjson + autoType"三个要素定位:

关键词(源码 / 配置 / 启动参数)

复制代码
JSON.parse(                 # 目标类型未知,重点
JSON.parseObject(           # 看是否给了固定 class;没给的要评估
setAutoTypeSupport(true)
fastjson.parser.autoTypeSupport
addAccept(                  # 看白名单是否过宽
setSafeMode(                # 有没有开;搜不到往往意味着没开
@type                       # 配置/日志里出现要警惕
Feature.SupportNonPublicField
JSONReader.Feature.SupportAutoType

危险模式

  1. JSON.parse(request.getParameter(...)) / JSON.parse(body):直接把请求体丢进去;

  2. @RequestBody 接收的是 Object / Map 而不是具体 DTO;

  3. 全局打开了 autoType,或用反射式 parseObject(json, Class.forName(userType));

  4. 版本低于 1.2.83,且没有 safeMode;

  5. 项目依赖树里有大量"可被组合的 gadget"(commons-collections、xbean、ignite、shiro 等)------这决定了绕过能不能落地。

看依赖

复制代码
mvn dependency:tree | grep -i fastjson    # 打印依赖树并筛选 fastjson 相关条目(含实际使用的版本)
# 关注版本号:< 1.2.83 需重点评估;同时看是否混入了危险 gadget 库

预期输出示例(列出实际依赖的版本):

复制代码
[INFO] +- com.alibaba:fastjson:jar:1.2.24:compile
[INFO] \- com.alibaba.fastjson2:fastjson2:jar:2.0.65:compile

只要看到 fastjson 1.x 且版本低于 1.2.83,就应重点评估;再结合是否开启 autoType 与依赖树里有无 gadget 判断可利用性。


三、流量与主机检测

1. 流量侧(网关 / NIDS / WAF / 日志)

Fastjson 攻击的流量特征集中在"输入里的类名":

  • JSON 请求体中出现 "@type",尤其是值包含 com.sun、java.lang、javax.naming、org.apache 等;

  • 出现 JdbcRowSetImpl、TemplatesImpl、dataSourceName、_bytecodes、_outputProperties 等字段;

  • 出现 ldap://、rmi://、dns 等外联特征;

  • _bytecodes 后面跟着长 Base64 串。

WAF 规则示例(示意,非万能):命中 "@type" 且同时命中 JdbcRowSetImpl|TemplatesImpl|ldap://|rmi:// 则告警/拦截。务必记住 :WAF 可以被变形绕过(大小写、编码、L...;、缓存写法等),它只能降低风险,不能替代根因修复。

2. 主机侧

  • 进程异常创建子进程(Runtime.exec / ProcessBuilder 触发 bash、curl、wget);

  • 应用进程产生到内网 LDAP/RMI 端口的异常外联;

  • 临时目录出现可疑 .class / .jar 落盘;

  • 日志里出现 autoType is not support 的突发大量记录------可能是攻击者在试探 payload(这条非常实用:攻击者会不断换写法,被拦截也会留痕)。

3. 典型案例的处置闭环

  1. 发现 :日志/告警出现 @type、ldap://、autoType is not support;

  2. 定位:确认受影响服务与 fastjson 版本、是否开启 autoType;

  3. 阻断:下线/隔离,限制出网;

  4. 修复 :升级 1.2.83+/fastjson2,或开 safeMode,改 JSON.parse 为固定类型;

  5. 排查:检查是否已被利用(子进程、外联、落盘、账号);

  6. 复盘:加检测规则、收敛依赖树。


四、一张"防御对照表"

措施 属于 能否根治 说明
用固定类型的 parseObject 代码 ✅ 目标类型固定,@type 失去作用
关闭 autoType / safeMode 配置 ✅(基本) 直接不启用该能力
升 1.2.83+ / fastjson2 升级 ✅ 消除已知绕过
最小白名单 配置 ⚠️ 取决于白名单是否真的最小
升级 JDK / 关 JNDI 远程加载 环境 ❌ 只挡住 JNDI 类链,TemplatesImpl 等仍可能
WAF / 出网管控 边界 ❌ 纵深防御,可被绕过

五、总结

  1. 为什么"用固定的目标类型解析"能从根上阻止 autoType 攻击?

  2. safeMode 和"关闭 autoType"有什么区别?为什么官方推荐两者都考虑?

  3. 审计时,除了 grep JSON.parse,还要看哪两样东西才能判断"是否真的可被利用"?

  4. 日志里出现大量 autoType is not support 意味着什么?怎么处置?

  5. 为什么说"WAF 不能替代修复"?

相关推荐
qetfw3 小时前
Debian SSH 安全配置:端口、来源限制与免密登录
linux·安全·debian·ssh
砚凝霜4 小时前
【软考信息安全】第十二章 网络安全审计概述与分类
网络·安全·web安全
大鹏的NLP博客4 小时前
Rust 的本质:用数学约束实现编译期内存安全
安全·rust
迪康妍妍4 小时前
终端安全实战:用迪康终端安全管理系统实现U盘四分档管控与全量审计
android·运维·网络·安全·电脑
YOLO数据集集合4 小时前
空中鸟类检测数据集 | 单目标 鸟类检测 生态监测 鸟击防范 目标检测9174期
安全·yolo·目标检测·飞鸟数据集·飞鸟
每天题库4 小时前
登高架设作业考试题库大全 核心考点真题刷题备考通关秘籍
学习·安全·考试·题库·考证
小蒋观天下16 小时前
专项方案:大场景港口AI安防、多干扰环境下的算法调优与落地实操
人工智能·深度学习·算法·安全·机器学习·计算机视觉·ai大模型
谢亮_vipxieliang17 小时前
Kubernetes 1.36 深度解读:从 kubelet 安全到 GPU 原生调度的 70 项改进
安全·kubernetes·kubelet
梦帮科技17 小时前
【3.0修订版】跨链中继与事件编排:Relayer 监听、多签验证与故障自愈
web安全·金融·区块链·密码学·智能合约·安全架构·信任链