最稳妥的方案是彻底避免使用 Java 原生序列化机制处理外部不可信数据。如果业务无法避免,必须实施严格的类白名单校验,并配合依赖包版本加固。
先说结论:Java 原生反序列化风险极高,除非内部可信通道,否则不应直接接收外部序列化对象。
- 先判断:确认业务是否真的必须使用 Java 原生序列化协议传输数据,优先替换为 JSON。
- 优先做:若必须使用,立即实施类白名单过滤,自定义 ObjectInputStream 子类。
- 再验证:通过漏洞扫描工具或手动构造测试数据确认防护生效,内网接口同样需要防护。
完整代码实现示例
以下是一个完整的白名单校验输入流实现,包含白名单初始化逻辑。请根据实际业务包名调整 whitelist 内容。
import java.io.*;
import java.util.*;
public class ValidatingObjectInputStream extends ObjectInputStream {
private static final Set<String> WHITELIST = new HashSet<>();
static {
// 初始化白名单,仅允许必要的业务类和基础类
WHITELIST.add("com.example.business.User");
WHITELIST.add("java.lang.String");
WHITELIST.add("java.util.ArrayList");
// 禁止所有危险集合类 gadget,除非业务强依赖且已加固
// WHITELIST.add("org.apache.commons.collections4.functors.InvokerTransformer");
}
public ValidatingObjectInputStream(InputStream in) throws IOException {
super(in);
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
if (!WHITELIST.contains(desc.getName())) {
throw new InvalidClassException("Unauthorized deserialization attempt: " + desc.getName());
}
return super.resolveClass(desc);
}
}
// 使用示例
// try (ValidatingObjectInputStream ois = new ValidatingObjectInputStream(inputStream)) {
// Object obj = ois.readObject();
// } catch (Exception e) {
// logger.error("Deserialization failed", e);
// }依赖包版本加固
许多反序列化漏洞源于第三方库中的 Gadget Chain。请检查并升级以下常见高危依赖:
- commons-collections: 升级至 3.2.2+ 或推荐使用 commons-collections4 4.4+ 及以上版本。
- commons-beanutils: 升级至 1.9.4+ 及以上版本。
- groovy: 升级至 2.4.8+ 及以上版本。
建议使用 OWASP Dependency-Check 定期扫描项目依赖:
./dependency-check.sh `--scan` ./path/to/your/project `--format` HTML分步处理与验证
- 排查入口:全局搜索
ObjectInputStream、XMLDecoder、readObject等关键词,定位所有反序列化点。 - 实施白名单:部署上述
ValidatingObjectInputStream,确保默认拒绝所有未显式允许的类。 - 网络层防护:在 WAF 或 RASP 层面开启反序列化攻击检测规则,作为最后一道防线。
- 验证生效:在测试环境使用安全的 PoC 工具尝试发送恶意序列化数据,确认服务端抛出
InvalidClassException且无命令执行。
常见坑与风险警示
- 白名单维护成本:业务迭代新增类时忘记更新白名单会导致功能报错。建议建立自动化测试流程,在 CI/CD 阶段验证白名单覆盖度。
- 内网零信任原则:严禁认为内网接口不需要防护。内网横向移动风险同样存在,所有反序列化入口必须实施同等强度的校验。
- 框架默认配置:部分旧版框架(如某些 RPC 框架)默认开启不安全反序列化,需查阅框架文档手动关闭或升级版本。
- 继承链风险:白名单校验仅针对类名,若允许的类中存在不安全方法,仍可能被利用。尽量只允许 DTO 等纯数据类。