Java 安全 — 反序列化(原生类)

序列化:将 Java 对象转换为字节流。
反序列化:将字节流还原为 Java 对象。

  • 格式特征:Java 序列化头部通常为字节 ac ed 00 05;Base64 编码序列化常见前缀 rO0AB

  • 常见类别:原生序列化(ObjectInputStream/XMLDecoder/SnakeYaml 等)、第三方组件序列化(Fastjson/Jackson/XStream 等)。


原生反序列化相关函数与注记

  • ObjectInputStream.readObject():Java 原生反序列化入口。

  • XMLDecoder:基于 XML 的反序列化实现。

  • SnakeYaml:YAML 1.1 规范处理器,支持 Java 对象序列化/反序列化。

  • 注意:欲被序列化的类需实现 java.io.Serializable 接口。


第三方组件反序列化(代表性库与触发点)

  • Log4j

    • 描述:Apache 日志框架。历史链式利用与 JNDI 相关。

    • 常见触发点:logger.error(...), logger.info(...)(与链式利用结合时)。

  • Shiro

    • 描述:认证/授权框架。

    • 常见触发点:CookieRememberMeManager(反序列化 Cookie 导致利用)。

  • Jackson

    • 描述:流行 JSON 解析器。

    • 常见触发点:ObjectMapper.readValue(...) / readValue

  • XStream

    • 描述:XML > 对象映射库。

    • 常见触发点:XStream.fromXML(...)

  • Fastjson

    • 描述:阿里巴巴的 JSON 解析器。

    • 常见触发点:JSON.parse(...), JSON.parseObject(...)


JNDI 注入(原理与版本演进)

  • JNDI:Java Naming and Directory Interface,用于查找/访问资源,支持协议包括 LDAP、RMI、CORBA、DNS 等。

  • 常见载体:RMI(远程方法调用)、LDAP(目录服务)。

版本与防护演化(关键系统属性)

  • java.rmi.server.useCodebaseOnly=true(JDK 6u45 / 7u21 起)—— 限制 RMI 类加载来源。

  • com.sun.jndi.rmi.object.trustURLCodebase=false(JDK 6u141 / 7u131 / 8u121 起)—— 禁止 RMI/CORBA 远程 codebase 加载。

  • com.sun.jndi.ldap.object.trustURLCodebase=false(JDK 6u211 / 7u201 / 8u191 起)—— 禁止 LDAP 远程 codebase 加载。

提示:不同 JDK 版本差异会影响可利用性;测试常见版本(如 8u65、8u292 等)以验证是否存在绕过或可利用路径。


审计要点(Sink 列表)

代码审计时重点检查以下点(可能为反序列化或链式利用入口):

  1. ObjectInputStream.readObject

  2. XMLDecoder.readObject

  3. Yaml.load / SnakeYaml.load

  4. XStream.fromXML

  5. ObjectMapper.readValue(Jackson)

  6. JSON.parse, JSON.parseObject(Fastjson)

  7. CookieRememberMeManager(Shiro)

  8. logger.error, logger.info(与链条相关)


利用与参考项目


简明防御建议

  • 尽量避免对不受信任的数据进行反序列化;优先使用受限的 JSON 解析器并开启白名单策略。

  • 对输入来源进行严格校验与白名单控制,避免直接传入反序列化 API。

  • 升级 JDK 并设置 JNDI 相关安全属性(参照官方建议)。

  • 使用反序列化防护库、序列化黑名单/白名单机制或禁用不必要的可序列化类。

  • 审计时结合依赖的 CVE 数据与项目历史漏洞进行风险评估。