XML 外部实体 XXE 是应用开启了 XML 外部实体解析,让攻击者借解析器读取服务器本地文件、发起内部服务请求;不安全的反序列化则是应用对不可信数据做反序列化,攻击者通过构造特殊对象在反序列化时执行代码。两者都发生在“解析/还原数据”这一层,共同的续法是收紧解析器与数据来源。
第四幕开讲的是“替你做解析的代码”。多数开发以为“按官方文档调用解析库”就安全,其实解析器的默认行为未必安全。XXE 与反序列化是两个最有代表性的“解析层暗雷”,一个在医院、企业导入导出系统里高发,一个在注册克标语言生态里屡见报端。
XML 允许在 DTD 里定义实体,而其中的外部实体能引用外部资源。若解析器开了外部实体且没限制,攻击者提交:
<?xml version="1.0"?> <!DOCTYPE x [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root>&xxe;</root>
解析时 &xxe; 会被替换成 /etc/passwd 的文件内容,经页面回显或报错泄漏出来。进一步还能用 http:// 协议打内网服务。它在以下场景特别常见:上传或接收 XML 的接口、文档/配置文件导入导出、SOAP 风格接口。解析器默认允许外部实体,恰恰是漏的根源。
把对象序列化成字节/字符串存起来、需要时再还原,是常见的缓存与状态手段。但若数据来自不可信来源,攻击者构造一个“还原后会触发危险动作”的特殊对象(如命令执行、文件写入),反序列化一瞬间就落地执行。语言生态里有经典反序列化链,前提往往只是“应用对不可信字节流调了还原函数”。难度越高,命中一次损失越大——可能直接拿操作系统权限。
这两个“解析层暗雷”各有各的触发开关,防御按钮也都明确。

💡 关键直觉:看到“解析”“还原”“导入”“导出”四个词,就要自动联想到这两个漏洞。它们共用同一个信号:你的程序在“把一串陌生字节变成结构化东西”,而这一变形过程常比业务逻辑更容易出洞。
背景:一个接收 XML 且未关外部实体的演示接口。操作:提交含文件协议外部实体的 XML。结果:接口响应里回显了本地文件内容,XXE 成立。解读:解析器默认开启外部实体,实体引用被还原成文件内容。变式:在解析配置里关闭外部实体/禁用 DTD,重复提交同一 XML,实体不再被解析、接口拒绝而非回显,XXE 被封死。同样思路给数据流接入点换成白名单类还原,反序列化链也被切断。
两者常被并列,但触发位置和后果并不相同,可以放成一张对照。XXE 的问题是“解析 XML 时解析器太慷慨”,输错的是配置和 DTD 开关,危害以读文件、打内网为主,攻击者对 payload 形状有较多约束。反序列化的问题是“还原对象时信任了外来字节流”,输错的是数据来源和调用入口,危害往往直达代码执行、拿下更高权限。给一个记忆点:XXE 是“解析器把我的数据当成了它的功能”,反序列化是“还原器把我的对象当成了它的指令”。排查时看到 XML 就查外部实体开关,看到还原函数就查数据来源白名单,两条线索各走各的。
这两种漏洞有个共同陷阱:团队常以为“这个接口是内部调用、外人碰不到”,于是在解析和还原上放松了把关。但内部接口也可能被上游其他漏洞带偏,或经 SSRF、越权、开放导出被间接触达。所以“输入是否可信”的判定不该看“调用方是谁”,而该看“这份数据能不能被外部间接改变”。只要存在让陌生字节变成结构化数据的路径,就要按可构造数据对待——这正是第一幕种下的“输入越界”结论在解析层的重演。
与其全靠记性提醒“此处要关外部实体”,不如把解析层准入做成一道统一的闸门。凡是进系统的结构化数据,先过一个“红绿灯”判定:红灯直接拒绝——不可信来源、无认证入口带来的对象流/XML 一律不解析不还原,直接报“不支持的格式”;黄灯须把关——来源受限但可能被间接触达的数据,严格按白名单类库、关闭外部实体并做类型校验后再进;绿灯才放行——确认为内部可信且版本已修补的解析调用。把规则写进公共的解析封装,而不是散落在每个业务方法里各自决定,能保证“新接口默认就走安全解析”,而不是依赖某个开发记得关开关。这也是把第三幕“输入不信任度打分”的方法,落到了解析这个具体动作上。