XXE漏洞即XML外部实体注入漏洞,核心成因是XML解析器默认开启了外部实体解析功能,攻击者可以构造包含恶意外部实体的XML数据,让解析器执行非预期的操作,比如读取服务器上的敏感文件、探测内网服务状态等。该漏洞在需要处理外部传入XML数据的场景中非常常见,比如接口接收XML格式的请求参数、解析用户上传的XML文件等。

XXE漏洞的产生原理
XML规范中允许定义外部实体,通过<!ENTITY>声明可以引用外部的资源,比如本地文件、远程URL等。如果XML解析器没有禁用外部实体解析,当传入的XML数据中包含恶意定义的外部实体时,解析器就会执行对应的引用操作,从而触发漏洞。
一个简单的恶意XML payload示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<foo>&xxe;</foo>
上面的payload中定义了名为xxe的外部实体,指向服务器本地的/etc/passwd文件,当解析器解析这段XML时,会将xxe实体替换为文件内容,攻击者就能获取到敏感文件信息。
常见XXE漏洞攻击场景
- 读取本地敏感文件:通过file协议的外部实体,读取服务器上的配置文件、密码文件等,比如读取Windows系统的
C:windowswin.ini,Linux系统的/etc/shadow等。 - 内网服务探测:通过http协议的外部实体,访问内网的端口和服务,根据返回结果判断内网服务的存活状态,比如访问
http://192.168.0.1:8080判断该端口是否开放。 - 发起SSRF攻击:利用外部实体让服务器向第三方服务发起请求,比如访问攻击者控制的远程服务器,获取服务器的网络信息或者执行进一步的攻击。
- 拒绝服务攻击:构造递归的外部实体定义,让解析器陷入无限递归,消耗大量服务器资源,导致服务不可用。
解析XML时防范XXE漏洞的方法
防范XXE漏洞的核心思路是禁用XML解析器的外部实体解析功能,或者过滤传入的XML数据中的恶意实体声明。不同编程语言的XML解析库有不同的配置方式,下面是常见语言的防范示例。
Java语言防范方法
Java中常用的XML解析器有DOM、SAX、StAX等,大部分解析器都提供了禁用外部实体的配置选项,以DOM解析为例:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
public class XmlParserUtil {
public static Document parseXml(String xmlContent) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// 禁用DOCTYPE声明,从根源阻止外部实体定义
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 禁用外部通用实体
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
// 禁用外部参数实体
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// 忽略XML中的外部DTD
factory.setXIncludeAware(false);
factory.setExpandEntityReferences(false);
DocumentBuilder builder = factory.newDocumentBuilder();
// 解析XML内容,这里需要将字符串转为输入流,实际使用时注意处理编码
return builder.parse(new java.io.ByteArrayInputStream(xmlContent.getBytes("UTF-8")));
}
}
Python语言防范方法
Python中常用的XML解析库有xml.etree.ElementTree、lxml等,以标准库的xml.etree.ElementTree为例,需要禁用外部实体解析:
import xml.etree.ElementTree as ET
from xml.sax.handler import feature_external_ges, feature_external_pes
def parse_xml(xml_content):
# 创建解析器,禁用外部通用实体和外部参数实体
parser = ET.XMLParser()
parser.parser.setFeature(feature_external_ges, False)
parser.parser.setFeature(feature_external_pes, False)
# 解析XML内容
root = ET.fromstring(xml_content, parser=parser)
return root
# 注意:如果需要使用lxml库,配置方式如下
# from lxml import etree
# parser = etree.XMLParser(resolve_entities=False, no_network=True)
# root = etree.fromstring(xml_content, parser=parser)
PHP语言防范方法
PHP中解析XML常用的函数是simplexml_load_string,默认情况下会解析外部实体,需要修改libxml的配置来禁用:
function parse_xml_safe($xml_content) {
// 禁用外部实体加载
libxml_disable_entity_loader(true);
// 解析XML,LIBXML_NOENT参数不要开启,避免解析实体
$xml = simplexml_load_string($xml_content, 'SimpleXMLElement', LIBXML_NONET);
return $xml;
}
通用防范建议
- 尽量不使用XML格式传输数据,优先选择JSON等更安全的格式,从根源减少XML解析的场景。
- 如果必须使用XML,对所有外部传入的XML数据进行校验,过滤掉<!DOCTYPE、<!ENTITY等关键字,避免恶意实体声明进入解析流程。
- 升级XML解析库到最新版本,很多新版本的解析库已经默认禁用了外部实体解析,降低配置失误的风险。
- 服务器层面限制XML解析进程的文件读取权限和网络访问权限,即使出现漏洞,也能减少攻击造成的影响。
总结
XXE漏洞的本质是XML解析器的外部实体功能被滥用,防范的核心就是禁用不必要的外部实体解析能力。开发者在处理XML数据时,只要根据所使用的解析库正确配置安全选项,同时做好输入校验和权限管控,就能有效规避该漏洞带来的安全风险。在实际开发中,建议将XML解析的安全配置封装成通用的工具方法,避免每个解析场景都单独配置出现遗漏。
XXE漏洞XML解析XML_external_entity漏洞防范安全配置修改时间:2026-06-25 07:12:35