静态代码分析是发现java反序列化风险最直接手段,关键在于识别重写且含未校验危险操作的readobject方法,需关注三类高危模式、主流工具配置、自定义规则补位及人工复核细节。

静态代码分析是发现 Java 反序列化风险最直接、最可控的手段之一。关键不在于“有没有调用 readObject”,而在于**是否重写了它,且内部存在未校验的危险操作**——这类代码本身就是漏洞温床,哪怕暂时没被外部触发,也属于高危待修复项。
盯紧三类高危 readObject 模式
工具要能识别出以下典型危险结构,而不是只找方法签名:
-
直接执行命令或反射调用:如
Runtime.getRuntime().exec(...)、ProcessBuilder(...).start()、Class.forName(...).getMethod(...).invoke(...) -
读取并未经校验地使用反序列化字段:比如从
in.readObject()或in.readUTF()获取字符串后,直接拼进 SQL、JS 表达式、文件路径或 ClassLoader 加载逻辑 -
调用可被子类覆写的非 final 方法:例如在
readObject中调用了this.getName()或validate(),而该方法未声明为final,攻击者可通过构造恶意子类绕过校验
主流工具配置要点(以 SpotBugs + FindSecBugs 为例)
SpotBugs 是目前对 Java 反序列化问题覆盖最成熟的免费方案,配合 FindSecBugs 插件可精准捕获:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 规则
SE_BAD_FIELD_IN_READOBJECT:检测readObject中访问了未声明transient的非基本类型字段(易导致 gadget 链利用) - 规则
SE_READ_OBJ_OVERWRITE:标记重写了readObject却未调用in.defaultReadObject()或in.readFields()的类(破坏默认流程,可能隐藏恶意逻辑) - 规则
SECPTI_INSECURE_DESERIALIZATION(FindSecBugs):识别ObjectInputStream构造后直接调用readObject(),且上下文无白名单/校验机制
使用时需确保编译级别 ≥ Java 8,并启用 -Xbootclasspath/p 加载 JDK 工具类,否则部分反射相关规则会漏报。
自定义规则补位(针对业务特有风险)
通用工具会漏掉业务层定制链路,建议补充简单正则或 AST 规则:
- 扫描所有实现
Serializable的类中是否存在private void readObject\(ObjectInputStream\)方法体 - 检查该方法内是否出现
exec、new ProcessBuilder、URL\.、Class\.forName、Method\.invoke等关键词(注意排除日志、测试等安全上下文) - 重点标记那些
readObject方法里调用了本类其他 public/protected 方法,且这些方法又涉及资源加载、表达式解析、模板渲染的类
人工复核不能跳过的三个细节
工具只能报线索,最终确认靠人:
- 看该类是否真的会被反序列化:搜索项目中是否有
new ObjectInputStream(...).readObject()调用点,尤其关注 HTTP 请求体解析、RPC 入参、缓存反序列化、消息队列消费者等入口 - 看
readObject是否做了有效校验:仅抛异常不算防护,必须验证字段值合法性(如正则、范围、白名单),且校验逻辑不能依赖外部可控对象 - 看是否配合
transient和readResolve:若敏感字段未设transient,或单例类没加readResolve,即使readObject当前干净,也属防御残缺
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










