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 列表)
代码审计时重点检查以下点(可能为反序列化或链式利用入口):
-
ObjectInputStream.readObject -
XMLDecoder.readObject -
Yaml.load/SnakeYaml.load -
XStream.fromXML -
ObjectMapper.readValue(Jackson) -
JSON.parse,JSON.parseObject(Fastjson) -
CookieRememberMeManager(Shiro) -
logger.error,logger.info(与链条相关)
利用与参考项目
简明防御建议
-
尽量避免对不受信任的数据进行反序列化;优先使用受限的 JSON 解析器并开启白名单策略。
-
对输入来源进行严格校验与白名单控制,避免直接传入反序列化 API。
-
升级 JDK 并设置 JNDI 相关安全属性(参照官方建议)。
-
使用反序列化防护库、序列化黑名单/白名单机制或禁用不必要的可序列化类。
-
审计时结合依赖的 CVE 数据与项目历史漏洞进行风险评估。