跳转到主内容
趣航编程网 - 趣学编程,启航技术之路!

XML文件上传路径遍历漏洞 如何防范../攻击

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

相关文章