XML 外部实体注入漏洞(XXE - XML External Entity Injection) 是一种常见的安全漏洞,通常发生在服务器端解析用户提供的 XML 数据时。攻击者利用这个漏洞可以控制服务器执行不安全的操作,或者窃取敏感数据。该漏洞源自 XML 解析器在处理 XML 文档时,错误地允许外部实体的解析和访问。以下是对该漏洞的详细说明和扩展。
1. 什么是 XML 外部实体(XXE)注入漏洞?
XML 外部实体注入漏洞(XXE)是一种攻击方式,攻击者通过提交特殊构造的 XML 数据,使得服务器在解析 XML 数据时,解析器尝试访问外部实体(例如文件、URL 或其他资源)。如果服务器没有适当的安全控制,恶意用户可以借此漏洞执行多种攻击:
-
信息泄露:攻击者可以通过解析器读取服务器上敏感的本地文件,例如
/etc/passwd
、/etc/shadow
或其他重要配置文件。 - 拒绝服务攻击(DoS):攻击者通过构造恶意的 XML 数据,使得服务器不断加载外部实体,从而消耗资源导致服务不可用(如通过“千年蟲”攻击)。
- 远程代码执行:如果 XML 外部实体指向一个恶意服务器,攻击者可以通过发送恶意请求,让服务器加载并执行远程代码。
- 绕过身份验证:攻击者可以借此漏洞绕过某些身份验证机制,或者访问通常无法直接访问的资源。
2. XXE 漏洞的工作原理
XXE 漏洞的本质是 XML 解析器处理 XML 文件时错误地解析外部实体(Entities),这些外部实体的内容通常是一个 URI 或路径。XML 外部实体定义允许 XML 文档引用外部资源。一个典型的 XML 外部实体定义如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >] >
<foo>&xxe;</foo>
在上面的例子中,xxe
是一个外部实体,指向 /etc/passwd
文件。当服务器解析这个 XML 文件时,它会尝试加载并显示这个文件的内容,攻击者因此能够访问系统的敏感信息。
3. 如何触发 XXE 漏洞?
攻击者通常会通过以下步骤触发 XXE 漏洞:
-
构造恶意的 XML 文件:攻击者构造一个包含外部实体引用的 XML 数据。例如,通过将恶意的
<!ENTITY>
标签嵌入到 XML 文档中,指向敏感的本地文件或外部服务器。 - 提交给服务器解析:攻击者将该 XML 文件提交给服务器端,通常通过提交表单、API 请求或者文件上传等方式。
- 服务器解析并执行外部实体:如果服务器未正确配置或未禁用外部实体解析,XML 解析器会处理这些外部实体,导致信息泄露或执行其他恶意行为。
4. 防御措施
为了防止 XXE 漏洞,许多现代编程语言和库已经采取了默认禁用外部实体解析的策略,防止恶意输入被解析。以下是一些常见的防护措施:
-
禁用外部实体解析:在解析 XML 数据时,确保禁用外部实体的解析功能。许多 XML 解析库(如 PHP 的
libxml
、Python 的lxml
等)提供了禁用外部实体解析的选项。-
在 PHP 中,可以使用
libxml
来禁用外部实体解析:libxml_disable_entity_loader(true);
-
在 Java 中,可以通过设置
XMLInputFactory
配置来禁用外部实体解析:XMLInputFactory factory = XMLInputFactory.newInstance(); factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
-
-
使用白名单:如果必须允许 XML 文档中引用外部实体,可以限制允许加载的外部实体的源,仅允许信任的来源。
-
使用现代解析器:许多现代 XML 解析器(如 libxml2 2.9.0 及以上版本)默认禁用外部实体解析。确保使用最新版本的解析器,以利用这些内建的安全机制。
-
输入验证与过滤:对用户输入的 XML 数据进行严格的验证和过滤,防止注入恶意的 XML 实体。
-
安全配置:确保服务器上的文件系统权限正确配置,防止敏感文件暴露给不必要的进程和用户。
5. 案例:PHP 中的 XXE 漏洞模拟
为了演示 XXE 漏洞的触发,下面是一个在 PHP 环境中开启外部实体解析的示例:
libxml_disable_entity_loader(false); // 手动启用外部实体解析
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >] >
<foo>&xxe;</foo>
XML;
$doc = new DOMDocument();
$doc->loadXML($xml); // 解析XML,尝试加载外部实体
echo $doc->saveXML(); // 输出解析结果
在上面的示例中,libxml_disable_entity_loader(false)
手动启用了外部实体解析。攻击者通过传入类似的恶意 XML 数据,服务器会试图加载 /etc/passwd
文件并将其内容输出。
6. 总结
XXE(XML 外部实体注入)漏洞是一种常见且危险的攻击方式,攻击者可以利用它访问敏感信息、触发拒绝服务攻击,甚至执行远程代码。为了防止这种漏洞,开发者应始终确保:
- 使用安全的 XML 解析器配置,禁用外部实体解析。
- 定期更新库和框架,确保使用最新的安全版本。
- 对外部输入进行严格的验证和过滤。
现代编程语言和库通常已提供针对 XXE 漏洞的防护措施,但开发者仍需警惕潜在的配置不当和漏洞风险。
文笔生疏,措辞浅薄,望各位大佬不吝赐教,万分感谢。
免责声明:由于传播或利用此文所提供的信息、技术或方法而造成的任何直接或间接的后果及损失,均由使用者本人负责, 文章作者不为此承担任何责任。
转载声明:儒道易行 拥有对此文章的修改和解释权,如欲转载或传播此文章,必须保证此文章的完整性,包括版权声明等全部内容。未经作者允许,不得任意修改或者增减此文章的内容,不得以任何方式将其用于商业目的。
****:
https://rdyx0.blog.****.net/
公众号:儒道易行
https://mp.weixin.qq.com/mp/appmsgalbum?__biz=Mzg5NTU2NjA1Mw==&action=getalbum&album_id=1696286248027357190&scene=173&from_msgid=2247485408&from_itemidx=1&count=3&nolastread=1#wechat_redirect
博客:
https://rdyx0.github.io/
先知社区:
https://xz.aliyun.com/u/37846
SecIN:
https://www.sec-in.com/author/3097
FreeBuf:
https://www.freebuf.com/author/%E5%9B%BD%E6%9C%8D%E6%9C%80%E5%BC%BA%E6%B8%97%E9%80%8F%E6%8E%8C%E6%8E%A7%E8%80%85