跳转到主内容
极星编程网:以代码为星,赴技术山海!

Java XMLDecoder反序列化漏洞 避免使用XMLDecoder读取不信任数据

XMLDecoder不能读取不信任的XML数据,因为它会直接执行XML中声明的任意Java类构造、方法调用和字段赋值,等同于执行不受控的Java代码,极易被利用执行恶意操作。 XMLDecoder 为什么不能读不信任的 XML 数据 因为
XMLDecoder
会直接执行 XML 中声明的任意 Java 类构造、方法调用和字段赋值,等同于在 JVM 里跑了一段不受控的 Java 代码。只要攻击者能控制输入 XML,就能调用
Runtime.getRuntime().exec()
、写文件、加载恶意类——漏洞利用门槛极低,且无需任何依赖。 常见错误现象:
java.lang.ClassNotFoundException
看似是类找不到,实际可能是攻击者故意触发类加载失败来探测环境;更危险的是静默执行成功,连日志都不留。 使用场景:旧系统中用
XMLDecoder
做配置反序列化、UI 组件状态恢复、测试数据加载 参数差异:它不校验类名白名单,也不限制方法调用,
setAccessible(true)
和私有字段赋值默认全开 兼容性影响:JDK 8u121+ 默认禁用部分高危类(如
ProcessBuilder
),但绕过方式公开且简单,不能依赖这个“防护” 替代方案:用 JAXB 或 Jackson XML 替掉 XMLDecoder JAXB(
javax.xml.bind.JAXBContext
)和 Jackson XML(
XmlMapper
)都只做字段映射,不执行逻辑,前提是不用
@XmlJavaTypeAdapter
引入自定义反序列化器。 实操建议: 立即学习 “ Java免费学习笔记(深入) ”; 优先选
XmlMapper
:Jackson 对类型安全控制更细,可设
DefaultTyping.NON_FINAL
关闭自动类型识别 禁用 JAXB 的
setEventHandler
和
setSchema
外部实体加载(防 XXE) 所有目标类必须有无参构造函数 + public setter,否则解析失败而非执行任意代码 示例:用
XmlMapper
读取配置时,明确指定类型
mapper.readValue(xmlBytes, Config.class)
,不传
Object.class
如果必须保留 XMLDecoder,至少加三道隔离 这不是推荐做法,而是给无法立即下线的老系统兜底。核心思路是切断它接触真实类路径、系统资源和反射能力的通路。 用自定义
ClassLoader
加载
XMLDecoder
实例,只允许加载白名单里的几个基础类(如
java.lang.String
、
java.util.ArrayList
) 在
SecurityManager
策略中禁止
RuntimePermission("createClassLoader")
和
FilePermission
,JDK 17+ 需改用
System.setSecurityManager(null)
后自行拦截(因 SecurityManager 已废弃但未移除) 预处理 XML:用正则或 SAX 解析器先扫描是否含
、
、
,命中即拒收——注意别漏掉换行/空格绕过(如
method=
) 最容易被忽略的点:XMLDecoder 常藏在第三方库底层 很多老 UI 框架(如 Apache Pivot)、报表工具(JasperReports 早期版本)或序列化工具封装了
XMLDecoder
,你没直接写它,但它在运行时被调用。查法很简单: 启动时加
-verbose:class
,搜
XMLDecoder
类加载记录 用
jstack
抓到正在运行的线程栈,看是否有
XMLDecoder.readObject
调用链 检查
META-INF/MANIFEST.MF
里有没有
Implementation-Title: JavaBeans
相关描述 修复时别只改自己写的代码,得确认依赖树里所有 jar 是否已升级到修复版本——比如 JasperReports 6.0.0+ 才彻底弃用
XMLDecoder
。

相关文章