核心是拒绝执行不可信字节流中的任意逻辑,必须严格白名单限制可反序列化类(如java 9+ objectinputfilter)、禁用对http/消息队列等不可信源调用readobject()、替换为json等安全格式、升级加固commons collections等高危依赖,并辅以运行时监控与权限限制。

Java反序列化漏洞的防御不是靠某一个开关或一行代码就能解决的,核心在于:**拒绝执行不可信字节流中的任意逻辑**。它本质是信任边界失控——你让JVM去“还原对象”,结果却让它顺带执行了攻击者埋好的命令。
严格限制可反序列化的类(白名单机制)
Java 9 起引入 ObjectInputFilter,它是目前最直接、最推荐的防御手段。它能在 readObject() 执行前拦截并校验类名,只放行明确允许的类。
- 在创建
ObjectInputStream时设置过滤器:ObjectInputStream ois = new ObjectInputStream(input) {<br> @Override<br> protected Class> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {<br> return super.resolveClass(desc);<br> }<br>};<br>ois.setObjectInputFilter(createFilter()); - 定义白名单过滤器(例如只允许
com.example.model.*下的类):ObjectInputFilter filter = ObjectInputFilter.Config.createFilter("maxarray=100000;maxdepth=5;maxrefs=10000;com.example.model.*;!*"); - 注意:不能只靠黑名单(如禁止
Runtime),因为绕过方式太多;白名单才是根本解法。
避免对不可信数据调用 readObject()
这是最基础也最容易被忽视的一条。只要输入来源不可控(如HTTP请求体、消息队列内容、文件上传、前端传参),就绝对不要用 ObjectInputStream.readObject()。
- 检查代码中所有
new ObjectInputStream(...)和readObject()的调用点,确认其输入是否100%来自可信内部系统。 - 若必须传输结构化数据,改用无执行能力的格式:JSON(Jackson/Gson)、XML(JAXB,禁用外部实体)、Protocol Buffers 等。
- 特别警惕第三方组件:RMI、JMX、WebLogic T3、Shiro RememberMe、Fastjson 默认配置等,都可能隐式触发反序列化。
升级与加固依赖库
很多反序列化漏洞并非你写的代码出问题,而是用了带 gadget 链的旧版库。
- Apache Commons Collections 3.1–4.0 存在经典 RCE 链,升级到 4.1+ 或彻底移除不用。
- Fastjson 低于 1.2.83 有多个反序列化漏洞,启用
safeMode=true或迁移到 Jackson。 - Jackson-databind 启用
enableDefaultTyping()是高危操作,应禁用;升级到已修复版本(如 2.13.5+)。 - 使用工具扫描:
dependency-check、OWASP Dependency-Check、Trivy可识别含已知 gadget 的依赖。
运行时监控与纵深防御
即便做了白名单,仍建议增加一层感知能力,便于快速发现异常行为。
- 在 JVM 启动参数中添加:
-Djdk.serialFilter="maxarray=100000;maxdepth=5;maxrefs=10000;com.yourpackage.*;!*",作为全局兜底。 - 记录所有
readObject()调用的类名和调用栈,对非预期类名告警(如出现javax.naming.、org.apache.commons.collections.)。 - 限制应用权限:禁用
Runtime.exec、关闭 JNDI 查找(-Dcom.sun.jndi.rmi.object.trustURLCodebase=false)、最小化 Linux 用户权限。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











