应同时进行路径归一化校验和XML解析器安全配置:先用os.path.realpath()或Paths.get().toRealPath()解析用户路径并与白名单根目录比对前缀,再禁用DOCTYPE声明及外部实体加载。
XML解析时如何阻止
路径遍历
XML文件上传后若直接用用户输入的文件名拼接本地路径(比如读取
或外部实体),攻击者可通过
向上跳转目录,读取
或应用
配置文件
。关键不是“禁用外部实体”,而是从路径构造环节就切断遍历可能。
所有用户可控的文件名/路径参数必须经过
(Python)或
(Java NIO)解析后,再与白名单根目录比对前缀
禁止用
或正则简单过滤——
、
、
(Windows)仍可绕过
若使用
或
加载XML,必须显式关闭外部实体:设置
Java中SAX/DOM解析器的安全配置
默认
和
允许外部DTD和实体,这是
和路径遍历的共同入口。仅靠应用层校验路径不解决根本问题。
直接禁止
,最彻底
若业务必须支持DOCTYPE(极少见),则需配合
拦截所有
调用,返回空
注意:Tomcat 8.5+ 默认已禁用外部实体,但Spring Boot内嵌Tomcat若覆盖了
bean,仍可能回退到不安全状态
Python lxml与defusedxml的选型差异
默认开启外部实体,且
会自动加载
协议资源;而
是专为防御XXE设计的封装层,但不处理路径拼接逻辑。
elasticsearch-9.4.0 win
PHP中文网提供Elasticsearch 9.4.0 Windows 版本压缩包下载解压即用,内置 OpenJDK 无需额外配置 Java 环境。该版本重磅推出原生 Prometheus 支持、正式版 Elastic Workflows 以及基于 NVIDIA cuVS 的 GPU 加速向量索引,大幅提升 AI 检索与可观测性能力。建议前往官网下载,快速体验极速搜索与强大的数据分析功能。
下载
用
替代原生
,它会禁用
和
但
不管
里的文件路径——你仍需确保
是经
校验后的绝对路径
避免混用:
+ 手动设
易遗漏,不如直接切到
上传文件名的白名单校验不能只看扩展名
攻击者常传
或
绕过
后缀检查,更危险的是用
作文件名,诱导服务端解析非XML文件引发二次漏洞。
提取原始文件名后,先用
剥离路径,再用
校验格式
拒绝任何含
、
、
、
、
的文件名——不是过滤,是直接拒收
存储时强制重命名:
,彻底断开用户输入与文件系统路径的映射
路径遍历和XXE常共存,但修复点不同:前者卡在文件操作前的路径归一化与白名单比对,后者卡在XML解析器的feature开关。两个环节缺一不可,漏掉任意一个,
就可能穿透进来。
../document.dtd..//etc/passwdos.path.realpath()Paths.get().toRealPath()String.replace("../", "")....//%2e%2e%2f..\DocumentBuilderlibxml2setFeature("http://apache.org/xml/features/disallow-doctype-decl", true)SAXParserFactoryDocumentBuilderFactoryXXEDocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setXIncludeAware(false);disallow-doctype-declEntityResolverresolveEntityInputSourceDocumentBuilderFactorylxmletree.parse()file://defusedxmldefusedxml.lxml.fromstring()etree.fromstring()load_dtd=Trueresolve_entities=Truedefusedxmlparse("user_input.xml")user_input.xmlos.path.realpath()lxml.etree.parse()parser=XMLParser(resolve_entities=False)defusedxmlpayload.xml?x=1shell.xmll.xml../../config.yamlos.path.basename()re.match(r'^[a-zA-Z0-9_-]+\.xml$', name)./\%uuid4().hex + ".xml"../