防止反序列化炸弹攻击的核心是限制反序列化过程的资源消耗,需严格限制输入大小与结构深度、禁用危险机制、启用沙箱约束,并优先采用不可序列化的安全数据格式。

防止反序列化炸弹攻击,核心是**限制反序列化过程的资源消耗**——不能让一段恶意构造的序列化数据,在反序列化时触发无限嵌套、超大集合、重复引用或递归膨胀,最终拖垮 CPU 和内存。
严格限制反序列化输入的大小与结构深度
在接收序列化数据(如 JSON、XML、Java Object Stream、YAML 等)前,先做轻量预检:
- 对字节流或字符串设置硬性长度上限(例如 JSON 不超过 1MB,Java 序列化流不超过 512KB),超出直接拒绝
- 使用支持深度限制的解析器:Jackson 可配
DeserializationFeature.FAIL_ON_TRAILING_TOKENS+ 自定义BeanDeserializerModifier拦截深层嵌套;Gson 提供setMaximumNestingDepth(10) - 对 XML 使用
SecureXMLFactory禁用 DTD 和外部实体,并设置setMaxChildElements(1000)、setMaxAttributesPerElement(50)等防护参数
禁用危险的反序列化机制与类型
很多反序列化炸弹依赖反射调用或特殊类加载行为:
- Java 中禁用
ObjectInputStream,改用白名单驱动的反序列化库(如 Jackson 的@JsonCreator+PolymorphicTypeValidator),显式声明允许反序列化的类 - 禁用 YAML 的
!!java.*标签和 SnakeYAML 默认的UnsafeConstructor,强制使用SafeConstructor或自定义Construct实现 - Spring Boot 项目中,通过
spring.jackson.deserialization.fail-on-unknown-properties=true防止未知字段引发意外逻辑
启用反序列化沙箱与运行时资源约束
即使代码逻辑有疏漏,也要让攻击无法耗尽系统资源:
- 为处理反序列化的线程池设置独立的 JVM 参数,如
-Xmx512m -XX:+UseSerialGC,避免影响主服务内存 - 在容器环境(Docker/K8s)中限制单个 Pod 的 CPU 和内存配额(
limits.cpu=500m, limits.memory=1Gi) - 关键服务可引入 Java Agent(如 OpenRASP)监控
ObjectInputStream.readObject()调用栈,发现深层嵌套或高频反射时自动中断
优先采用不可序列化、无状态的数据交换格式
从根本上减少攻击面:
- 内部服务通信尽量用 Protobuf 或 FlatBuffers —— 它们不支持任意对象图、无反射、无运行时类型解析,天然免疫反序列化炸弹
- 对外 API 统一使用 JSON Schema 校验请求体结构,结合网关层(如 Kong、APISIX)做字段级限长与嵌套层数校验
- 避免将用户输入直接传给
eval()、exec()、ObjectMapper.readValue(..., Object.class)这类“万能解析”操作
不复杂但容易忽略:一次反序列化请求可能瞬间创建数百万对象,防御不在事后杀毒,而在入口设卡、过程限流、执行隔离。

















