1. 漏洞简介

1.1 什么是 XXE 漏洞

XML 外部实体注入(也称为 XXE)是一个 Web 安全漏洞,允许攻击者干扰应用程序对 XML 数据的处理。它通常允许攻击者查看应用程序服务器文件系统上的文件,并与应用程序本身可以访问的任何后端或外部系统进行交互。

1.1.1 漏洞产生原因

某些应用程序使用 XML 格式在浏览器和服务器之间传输数据。执行此操作的应用程序几乎总是使用标准库或平台 API 来处理服务器上的 XML 数据。出现 XXE 漏洞的原因是 XML 规范包含各种潜在的危险功能,并且标准分析器支持这些功能,即使应用程序通常不使用这些功能也是如此。
XML 外部实体是一种自定义 XML 实体,其定义的值是从声明它们的 DTD 外部加载的。从安全角度来看,外部实体特别有趣,因为它们允许根据文件路径或 URL 的内容定义实体。

1.2 XXE 漏洞危害

在某些情况下,攻击者可以利用 XXE 漏洞执行服务器端请求伪造  (SSRF) 攻击,从而升级 XXE 攻击以破坏底层服务器或其他后端基础结构。

2. XXE 漏洞预防

2.1 检测 XXE

  • 绝大多数XXE漏洞都可以使用Burp Suite的Web漏洞扫描程序快速可靠地找到。
手动测试 XXE 漏洞通常涉及:
  • 通过基于已知操作系统文件定义外部实体并在应用程序响应中返回的数据中使用该实体来测试文件检索。
  • 通过基于您控制的系统的 URL 定义外部实体,并监视与该系统的交互,测试盲XEE。
  • 通过使用 XInclude 攻击尝试检索已知的操作系统文件,测试在服务器端 XML 文档中是否容易包含用户提供的非 XML 数据。

2.2 防止 XXE

  • 几乎所有 XXE 漏洞都是由于应用程序的 XML 分析库支持应用程序不需要或不打算使用的潜在危险的 XML 功能而产生的。防止XXE攻击的最简单,最有效的方法是禁用这些功能。
  • 通常,禁用外部实体的解析并禁用对 的支持就足够了。这通常可以通过配置选项或以编程方式覆盖默认行为来完成。

3. XXE 漏洞利用

各种类型的XXE攻击:
  • 利用 XXE 检索文件,其中定义了包含文件内容的外部实体,并在应用程序的响应中返回。

3.1 响应有返回外部实体值

3.1.1 利用 XXE 检索文件

要执行从服务器文件系统检索任意文件的 XXE 注入攻击,您需要通过两种方式修改提交的 XML:
  • 引入(或编辑)一个元素,该元素定义包含文件路径的外部实体。
  • 编辑在应用程序响应中返回的 XML 中的数据值,以利用定义的外部实体。
例如,假设购物应用程序通过将以下 XML 提交到服务器来检查产品的库存水平:
应用程序不会对 XXE 攻击执行任何特定的防御措施,因此您可以利用 XXE 漏洞通过提交以下 XXE 负载来检索文件:/etc/passwd
此 XXE 负载定义一个外部实体,其值是文件的内容,并使用值中的实体。这会导致应用程序的响应包含文件的内容:&xxe;/etc/passwdproductId
对于实际的 XXE 漏洞,提交的 XML 中通常会有大量数据值,其中任何一个值都可能在应用程序的响应中使用。要系统地测试XXE漏洞,通常需要单独测试XML中的每个数据节点,方法是使用定义的实体并查看它是否出现在响应中。

3.1.2 利用 XXE 执行 SSRF 攻击

除了检索敏感数据之外,XXE攻击的另一个主要影响是它们可用于执行服务器端请求伪造(SSRF)。这是一个潜在的严重漏洞,在该漏洞中,服务器端应用程序可能会被诱使向服务器可以访问的任何 URL 发出 HTTP 请求。
若要利用 XXE 漏洞执行 SSRF 攻击,需要使用要作为目标的 URL 定义外部 XML 实体,并在数据值中使用定义的实体。如果可以在应用程序响应中返回的数据值中使用定义的实体,则您将能够从应用程序响应中的 URL 查看响应,从而获得与后端系统的双向交互。如果没有,那么您只能执行盲目的SSRF攻击(这仍然会产生严重后果)。
在以下 XXE 示例中,外部实体将导致服务器向组织基础结构中的内部系统发出后端 HTTP 请求:

3.1.3 通过文件上传进行XXE攻击

一些应用程序允许用户上传文件,然后在服务器端处理这些文件。某些常见文件格式使用 XML 或包含 XML 子组件。基于 XML 的格式的示例包括办公文档格式(如 DOCX)和图像格式(如 SVG)。
例如,应用程序可能允许用户上载图像,并在上载图像后在服务器上处理或验证这些图像。即使应用程序希望接收 PNG 或 JPEG 等格式,正在使用的图像处理库也可能支持 SVG 图像。由于 SVG 格式使用 XML,因此攻击者可以提交恶意 SVG 图像,从而针对 XXE 漏洞到达隐藏的攻击面。

3.1.4 通过修改的内容类型进行XXE攻击

大多数 POST 请求使用由 HTML 表单生成的默认内容类型,例如 。某些网站希望接收此格式的请求,但会容忍其他内容类型,包括 XML。application/x-www-form-urlencoded
例如,如果普通请求包含以下内容:
然后,您可以提交以下请求,并得到相同的结果:
如果应用程序允许消息正文中包含 XML 的请求,并将正文内容解析为 XML,则只需重新格式化请求以使用 XML 格式,即可到达隐藏的 XXE 攻击面。

3.2 盲 XXE 攻击

当应用程序容易受到 XXE 注入的攻击,但在其响应中不返回任何已定义的外部实体的值时,就会出现盲 XXE 漏洞。
这意味着无法直接检索服务器端文件,因此盲XXE通常比常规XXE漏洞更难利用。
您可以通过两种广泛的方式查找和利用盲目的 XXE 漏洞:
  • 您可以触发带外网络交互,有时还会泄露交互数据中的敏感数据。
  • 可以以错误消息包含敏感数据的方式触发 XML 分析错误

3.2.1 使用带外技术检测盲 XXE

您通常可以使用与 XXE SSRF 攻击相同的技术来检测盲 XXE,但会触发与您控制的系统的带外网络交互。例如,您可以按如下方式定义外部实体:
然后,您将在 XML 中的数据值中使用定义的实体。
此 XXE 攻击会导致服务器向指定的 URL 发出后端 HTTP 请求。攻击者可以监视生成的 DNS 查找和 HTTP 请求,从而检测 XXE 攻击是否成功。
有时,由于应用程序的某些输入验证或正在使用的 XML 解析器的一些强化,使用常规实体的 XXE 攻击会被阻止。在此情况下,您可能能够改用 XML 参数实体。
XML 参数实体是一种特殊类型的 XML 实体,只能在 DTD 中的其他位置引用。就目前而言,您只需要知道两件事。首先,XML 参数实体的声明在实体名称前包含百分比字符:
其次,参数实体使用百分比字符而不是通常的 & 符号进行引用:
这意味着您可以通过 XML 参数实体使用带外检测来测试盲 XXE,如下所示:
此 XXE 负载声明调用的 XML 参数实体,然后在 DTD 中使用该实体。这将导致对攻击者的域进行 DNS 查找和 HTTP 请求,从而验证攻击是否成功。

3.2.2 利用盲 XXE 带外泄露数据

通过带外技术检测盲XXE漏洞非常好,但它实际上并没有证明如何利用该漏洞。攻击者真正想要实现的是泄露敏感数据。这可以通过盲XXE漏洞实现,但它涉及攻击者在其控制的系统上托管恶意DTD,然后从带内XXE有效负载内调用外部DTD。
恶意 DTD 泄露文件内容的示例如下:/etc/passwd
此 DTD 执行以下步骤:
  • 定义一个名为 的 XML 参数实体,其中包含文件的内容。file/etc/passwd
  • 定义一个名为 的 XML 参数实体,其中包含另一个名为 的 XML 参数实体的动态声明。将通过向攻击者的 Web 服务器发出 HTTP 请求来评估实体,该请求包含 URL 查询字符串中实体的值。evalexfiltrateexfiltratefile
  • 使用实体,这将导致执行实体的动态声明。evalexfiltrate
  • 使用实体,以便通过请求指定的 URL 来评估其值。exfiltrate
然后,攻击者必须在他们控制的系统上托管恶意 DTD,通常是通过将其加载到他们自己的 Web 服务器上。例如,攻击者可能通过以下 URL 向恶意 DTD 提供服务:
最后,攻击者必须向易受攻击的应用程序提交以下 XXE 有效负载:
此 XXE 负载声明调用的 XML 参数实体,然后在 DTD 中使用该实体。这将导致 XML 分析器从攻击者的服务器获取外部 DTD 并对其进行内联解释。然后执行恶意 DTD 中定义的步骤,并将文件传输到攻击者的服务器。xxe/etc/passwd
此技术可能不适用于某些文件内容,包括文件中包含的换行符。这是因为某些 XML 分析器使用 API 获取外部实体定义中的 URL,该 API 验证允许出现在 URL 中的字符。在此情况下,可以使用 FTP 协议而不是 HTTP。有时,无法泄露包含换行符的数据,因此可以改为将 此类文件作为目标。/etc/passwd/etc/hostname

3.2.3 利用盲 XXE 通过错误信息检索数据

利用盲XXE的另一种方法是触发 XML 分析错误,其中错误消息包含要检索的敏感数据。如果应用程序在其响应中返回生成的错误消息,这将有效。
您可以使用恶意的外部 DTD 触发包含文件内容的 XML 分析错误消息,如下所示:/etc/passwd
此 DTD 执行以下步骤:
  • 定义一个名为 的 XML 参数实体,其中包含文件的内容。file/etc/passwd
  • 定义一个名为 的 XML 参数实体,其中包含另一个名为 的 XML 参数实体的动态声明。将通过加载名称包含实体值的不存在的文件来评估实体。evalerrorerrorfile
  • 使用实体,这将导致执行实体的动态声明。evalerror
  • 使用实体,以便通过尝试加载不存在的文件来计算其值,从而导致出现一条错误消息,其中包含不存在的文件的名称,即文件的内容。error/etc/passwd
调用恶意的外部 DTD 将导致类似以下内容的错误消息:

3.2.4 通过重新利用本地 DTD 来利用盲 XXE

上述技术适用于外部 DTD,但通常不适用于元素中完全指定的内部 DTD。这是因为该技术涉及在另一个参数实体的定义中使用 XML 参数实体。根据 XML 规范,这在外部 DTD 中是允许的,但在内部 DTD 中是不允许的(某些解析器可能会容忍它,但许多解析器不能。DOCTYPE
那么,当带外交互被阻止时,盲XXE漏洞呢?不能通过带外连接泄露数据,也不能从远程服务器加载外部 DTD。
在此情况下,由于 XML 语言规范中的漏洞,仍可能触发包含敏感数据的错误消息。如果文档的 DTD 使用内部和外部 DTD 声明的混合,则内部 DTD 可以重新定义在外部 DTD 中声明的实体。发生这种情况时,将放宽在另一个参数实体的定义中使用 XML 参数实体的限制。
这意味着攻击者可以从内部 DTD 中使用基于错误的 XXE 技术,前提是他们使用的 XML 参数实体正在重新定义在外部 DTD 中声明的实体。当然,如果带外连接被阻止,则无法从远程位置加载外部 DTD。相反,它需要是应用程序服务器本地的外部 DTD 文件
从本质上讲,攻击涉及调用恰好存在于本地文件系统上的 DTD 文件,并重新调整其用途,以触发包含敏感数据的解析错误的方式重新定义现有实体。
例如,假设服务器文件系统上有一个 DTD 文件的位置,并且此 DTD 文件定义了一个名为 的实体。攻击者可以通过提交如下所示的混合 DTD 来触发包含文件内容的 XML 分析错误消息:/usr/local/app/schema.dtdcustom_entity/etc/passwd
此 DTD 执行以下步骤:
  • 定义一个名为 的 XML 参数实体,其中包含服务器文件系统上存在的外部 DTD 文件的内容。local_dtd
  • 重新定义名为 的 XML 参数实体,该实体已在外部 DTD 文件中定义。该实体被重新定义为包含已描述的基于错误的 XXE 攻击,用于触发包含文件内容的错误消息。custom_entity/etc/passwd
  • 使用实体,以便解释外部 DTD,包括实体的重新定义值。这将导致所需的错误消息。local_dtdcustom_entity

3.2.5 查找现有 DTD 文件以重新调整用途

由于此 XXE 攻击涉及重新调整服务器文件系统上现有 DTD 的用途,因此关键要求是找到合适的文件。这实际上非常简单。由于应用程序返回 XML 分析器引发的任何错误消息,因此只需尝试从内部 DTD 中加载本地 DTD 文件,即可轻松枚举这些文件。
例如,使用 GNOME 桌面环境的 Linux 系统通常在 .您可以通过提交以下 XXE 负载来测试此文件是否存在,如果文件丢失,这将导致错误:/usr/share/yelp/dtd/docbookx.dtd
在测试了常见 DTD 文件列表以查找存在的文件后,您需要获取该文件的副本并对其进行检查以查找可以重新定义的图元。由于包含DTD文件的许多常见系统都是开源的,因此通常可以通过Internet搜索快速获取文件的副本。

参考文章

 
💡
本文章仅提供学习使用,有任何问题,欢迎您在底部评论区留言,一起交流~
 
 
反序列化漏洞XSS和CSRF区别