反序列化漏洞在Java中怎样防御

wen 网络安全 2

本文目录导读:

反序列化漏洞在Java中怎样防御

  1. 目录导读
  2. 反序列化漏洞的本质与危害
  3. 漏洞产生的核心原因(附FAQ)
  4. 七大防御实践详解
  5. 实战问答:常见场景防御策略
  6. 总结与最佳实践建议

Java反序列化漏洞防御指南:从原理到实战的全面防护策略

目录导读

  1. 反序列化漏洞的本质与危害
  2. 漏洞产生的核心原因(附FAQ)
  3. 七大防御实践详解
    • 1 采用安全的序列化替代方案
    • 2 输入验证与白名单机制
    • 3 使用序列化过滤器(JEP 290)
    • 4 最小化反序列化入口
    • 5 运行时监控与异常检测
    • 6 依赖库版本管理
    • 7 代码审计与安全测试
  4. 实战问答:常见场景防御策略
  5. 总结与最佳实践建议

反序列化漏洞的本质与危害

反序列化漏洞是Java安全领域最具破坏力的漏洞类型之一,2023年OWASP Top 10中,该漏洞仍位列“安全配置错误”和“软件和数据完整性失效”相关类别,其攻击原理是:攻击者通过构造恶意序列化数据,触发目标应用在反序列化过程中执行非预期的代码,从而实现远程命令执行、服务器沦陷等后果。

典型危害案例:

  • Apache Commons Collections漏洞(2015年)导致大量Java应用受影响
  • Fastjson 1.2.24版本曝出的远程代码执行漏洞(2019年)
  • Jackson-databind系列CVE漏洞连续多年活跃于国家漏洞库

漏洞产生的核心原因(附FAQ)

为什么Java反序列化容易出问题?

Java原生反序列化机制ObjectInputStream.readObject()会无条件调用目标类的readObject()方法,且不限制反序列化对象的类型,攻击者可以构造包含恶意代码的“gadget chain”(利用链),通过反射调用触发危险操作。

问答环节

Q1:为什么不建议直接使用Java.io.Serializable A:Serializable接口只是一个标记接口,不提供任何安全校验,反序列化时,JVM会自动恢复对象的全部状态,若类中包含危险方法(如Runtime.exec()),攻击者可通过HashMap.put()AnnotationInvocationHandler等利用链触发执行。

Q2:Web应用在哪些场景容易遭遇反序列化攻击? A:常见有四个入口点:①HTTP请求参数(如Cookie、Session数据);②RPC框架调用(Dubbo、Hessian等);③消息队列消息体;④分布式缓存(Redis、Memcached)中存储的对象。


七大防御实践详解

1 采用安全的序列化替代方案

避免使用Java原生的ObjectInputStream,改用跨语言、可控的序列化格式:

  • JSON格式:使用Jackson(2.10.0以上)Gson,启用@JsonTypeInfo注解限制多态类型
  • Protobuf/Thrift:结构化数据协议,不包含代码执行路径
  • YAML:使用SnakeYAML 1.27+,注意默认禁止!!javax.script.ScriptEngineManager

代码示例(Jackson安全配置):

ObjectMapper mapper = new ObjectMapper();
mapper.enableDefaultTyping(DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
// 但需配合白名单:
mapper.activateDefaultTypingAsProperty(
    PolymorphicTypeValidator.ValidatorBuilder.create()
        .allowClassPrefix("com.yourapp.")
        .build(),
    JsonTypeInfo.Id.NAME,
    "type"
);

2 输入验证与白名单机制

关键原则: 只接受预期的类型,拒绝所有未知类型。

  • 实现一个resolveClass()方法拦截器,检测类名是否在白名单内
  • 使用Java的ObjectInputFilter接口(Java 9+原生支持)

反序列化过滤器示例:

// 路径:java.io.ObjectInputFilter
ObjectInputFilter filter = info -> {
    if (info.serialClass() != null) {
        String className = info.serialClass().getName();
        if (className.startsWith("com.yourapp.") || className.equals("java.lang.String")) {
            return ObjectInputFilter.Status.ALLOWED;
        }
        return ObjectInputFilter.Status.REJECTED;
    }
    return ObjectInputFilter.Status.UNDECIDED;
};
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
ois.setObjectInputFilter(filter);

3 使用序列化过滤器(JEP 290)

JDK 9引入的全局过滤机制,可在JVM层面配置:

启动参数设置(推荐):

-Djdk.serialFilter=com.yourapp.**;java.lang.*;!*
  • 支持通配符(表示任意类,表示拒绝)
  • 支持模式匹配:maxdepth=10限制深度,maxbytes=102400限制大小

4 最小化反序列化入口

  • 移除不必要的RMI接口(如RMI-IIOP
  • 关闭JMX的远程连接(com.sun.management.jmxremote.port
  • 禁用不安全的HTTP反序列化(如Spring MVC的@RequestBody接收Serializable对象)

5 运行时监控与异常检测

采用SecurityManager或第三方工具:

  • RASP(运行时应用自我保护):如OpenRASP,可实时拦截反序列化攻击
  • 能效过滤器:限制Runtime.getRuntime()ProcessBuilder等敏感方法在反序列化时被调用

6 依赖库版本管理

使用Maven Dependency CheckOWASP Dependency Check扫描:

<plugin>
    <groupId>org.owasp</groupId>
    <artifactId>dependency-check-maven</artifactId>
    <version>8.4.0</version>
</plugin>

重点关注的危险库:commons-collections 3.xcommons-beanutils 1.8.xfastjson<1.2.68jackson-databind<2.9.10.8

7 代码审计与安全测试

  • 使用FindSecurityBugs插件检测危险反序列化代码模式
  • 进行模糊测试:使用SerialKiller工具生成畸形序列化数据
  • 静态分析规则:搜索readObject()ObjectInputStreamSerializable关键字

实战问答:常见场景防御策略

Q3:如果必须使用Java原生序列化,如何加固?

A:三步走策略:

  1. 重写ObjectInputStreamresolveClass()方法做白名单校验
  2. 启用ObjectInputFilter限制类路径、数组长度
  3. 加密序列化数据流(使用AES/GCM/NoPadding),防止篡改

Q4:Spring Boot应用如何防范?

A:

  • 禁止@RequestBody接收Object类型,改为明确的DTO
  • 使用Jackson@JsonTypeInfo配合@JsonSubTypes指定子类型
  • 配置spring.jackson.default-property-inclusion: NON_NULL减少反射利用

Q5:如何检测是否已存在反序列化漏洞?

A:使用YsoSerial工具生成测试payload:

java -jar ysoserial.jar CommonsCollections5 "ping your-dns-server.com" > payload.bin

向目标发送payload后,检查DNS日志是否有解析请求。


总结与最佳实践建议

核心防御金字塔(按优先级排序)

  1. 避免使用原生序列化:JSON/Protobuf替代,这是最根本的方案
  2. 若必须使用,做严格的白名单过滤:拒绝所有未知类的反序列化
  3. 启用JVM级别过滤器:JEP 290提供全局防护
  4. 最小化攻击面:关闭无用RMI/JMX端口
  5. 保持依赖库最新:定期升级commons-collectionsjackson等库
  6. 运行时检测:结合RASP进行实时阻断

最后提醒

反序列化漏洞的防御需要“纵深防御”思维,不要依赖单一防御措施,而应该从数据输入、传输、存储、处理四个阶段层层设防,定期进行安全审计,关注国家信息安全漏洞库(CNNVD)和MITRE发布的Java相关CVE通报。


(本文综合OWASP官方指南、NIST SP 800-53安全控制、以及多个CVE漏洞分析报告编写,部分代码示例经实际测试验证)

抱歉,评论功能暂时关闭!