java反序列化防护应采用白名单为主、黑名单为辅的混合策略,核心是在objectinputstream子类中重写resolveclass方法拦截非法类名;白名单只放行可信类,黑名单阻断已知危险类,需避免class.forname()加载及误配通配符。

Java 反序列化攻击防护中,黑白名单校验是简单有效的一线防御手段。核心思路是在反序列化前拦截非法类名,只允许白名单中的类被反序列化,或明确禁止黑名单中的高危类(如 org.apache.commons.collections 系列、javax.management.BadAttributeValueExpException 等)。关键不在“怎么写名单”,而在于“在哪拦截”和“怎么校验”——必须在反序列化入口(如 ObjectInputStream 子类)中重写 resolveClass 方法,否则名单形同虚设。
白名单机制:只放行可信类
白名单更安全,适合业务类明确、扩展性要求不高的场景。需预先收集所有可能被反序列化的业务类(如 DTO、VO、Entity),并确保其无危险逻辑(如重写了 readObject 且未校验输入)。
- 继承
ObjectInputStream,重写resolveClass - 在方法内检查
desc.getName()是否在预设白名单集合中(建议用Set<string></string>提升查找效率) - 不在白名单则直接抛出
InvalidClassException,中断反序列化流程 - 白名单应配置化(如读取 classpath 下的
safe-classes.txt),避免硬编码
黑名单机制:阻断已知危险类
黑名单响应快、易维护,适合快速封堵新曝漏洞(如 FastJSON 早期版本绕过),但无法防御未知利用链,仅作补充手段。
- 同样重写
resolveClass,但先判断类名是否匹配黑名单正则(如"^org\.apache\.commons\.collections\..*") - 匹配即拒绝,抛异常;不匹配才调用
super.resolveClass(desc) - 黑名单需定期更新(参考 OWASP Java Deserialization Cheat Sheet 或 CVE 公告)
- 注意通配符范围,避免误杀(例如
java.util.*会误拦合法集合类)
混合策略与注意事项
生产环境推荐“白名单为主 + 黑名单兜底”,兼顾安全性与兼容性。同时需规避常见陷阱:
- 不要在校验时依赖
Class.forName()加载类——可能触发静态初始化块或恶意代码 - 避免使用
ObjectInputStream默认构造器,必须用自定义子类实例 - 若使用 Jackson / FastJSON 等第三方库,需启用其内置反序列化防护(如 Jackson 的
PolymorphicTypeValidator) - 注意 JDK 9+ 模块系统影响,白名单类需确保模块可访问(如
java.base中的类默认放行)
实际代码片段示意
以下为轻量级白名单 ObjectInputStream 实现:
public class SafeObjectInputStream extends ObjectInputStream {
private static final Set<string> SAFE_CLASSES = Set.of(
"com.example.UserDTO",
"com.example.OrderVO",
"java.lang.String",
"java.util.ArrayList"
);
public SafeObjectInputStream(InputStream in) throws IOException {
super(in);
}
@Override
protected Class> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
String className = desc.getName();
if (!SAFE_CLASSES.contains(className)) {
throw new InvalidClassException("Unauthorized deserialization: " + className);
}
return super.resolveClass(desc);
}
}</string>
使用时替换原调用:new SafeObjectInputStream(inputStream)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











