发现并利用盲XXE漏洞
在这一节,我们将讲解什么是盲XXE注入,并描述发现和利用盲XXE漏洞的各种技术。
什么是盲XXE?
盲XXE漏洞是指应用程序容易受到XXE注入的攻击,但在其响应中不返回任何已定义的外部实体的值。这意味着无法直接检索服务器端文件,因此盲XXE通常比普通的XXE漏洞更难以利用。
有两种主要途径可以发现和利用盲XXE漏洞:
你可以触发带外网络交互,有时会在交互数据中泄露敏感数据。
你可以以某种方式触发XML解析错误,以便错误信息包含敏感数据。
使用带外技术检测盲XXE
通常可以使用与XXE SSRF攻击相同的技术来检测盲XXE,但要触发到你控制的系统的带外网络交互。例如,你可以定义一个外部实体,如下所示:
然后,你就可以在XML的数据值中使用已定义的实体。
这种XXE攻击会导致服务器向指定URL发起后端HTTP请求。攻击者可以监视由此产生的DNS查询和HTTP请求,从而检测到XXE攻击是否成功。
LAB
有时,由于应用程序的某些输入验证或正在使用的XML解析器的某些加固,使用常规实体的XXE攻击会被阻止。在这种情况下,你也许可以改用XML参数实体。XML参数实体是一种特殊类型的XML实体,只能在DTD内部的其他位置引用。就目前而言,你只需要了解两件事情。首先,XML参数实体的声明包括实体名称前的百分号字符:
其次,参数实体的引用使用百分号字符,而不是通常的和号(&):
这意味着你可以通过XML参数实体使用带外检测来测试盲XXE,如下所示:
这个XXE有效载荷声明了一个名为xxe
的XML参数实体,然后在DTD中使用该实体。这将导致向攻击者域发起DNS查询和HTTP请求,以验证攻击是否成功。
LAB
利用盲XXE带外渗出数据
通过带外技术检测盲XXE漏洞固然很好,但它实际上并未展示如何能够利用这种漏洞。攻击者真正想要实现的是外泄敏感数据。这可以通过盲XXE漏洞实现,但需要攻击者在他们控制的系统上托管一个恶意的DTD,并在带内XXE有效载荷中调用外部DTD。
一个用于外泄/etc/passwd
文件内容的恶意DTD示例如下所示:
这个DTD执行以下步骤:
定义一个名为
file
的XML参数实体,其中包含/etc/passwd
文件的内容。定义一个名为
eval
的XML参数实体,其中包含另一个名为exfiltrate
的XML参数实体的动态声明。exfiltrate
实体将通过向攻击者的Web服务器发起HTTP请求进行评估,该请求在URL查询字符串中包含file
实体的值。使用
eval
实体,这导致exfiltrate
实体的动态声明被执行。使用
exfiltrate
实体,以便通过请求指定的URL来评估其值。
然后,攻击者必须在他们控制的系统上托管恶意DTD,通常是将其加载到他们自己的Web服务器上。例如,攻击者可能在以下URL上提供恶意DTD:
最后,攻击者必须向存在漏洞的应用程序提交以下XXE有效载荷:
此XXE有效载荷声明了一个名为xxe
的XML参数实体,随后在DTD中使用该实体。这将导致XML解析器从攻击者的服务器获取外部DTD并对其进行内联解释。然后,恶意DTD中定义的步骤将被执行,/etc/passwd
文件将被传输到攻击者的服务器。
注意
这种技术可能无法处理某些文件内容,包括
/etc/passwd
文件中包含的换行符。这是因为一些XML解析器会使用API获取外部实体定义中的URL,该API会验证URL中允许出现的字符。在这种情况下,可以使用FTP协议而非HTTP。有时,可能无法外泄包含换行符的数据,因此可以选择/etc/hostname
文件作为目标。
LAB
利用盲XXE通过错误信息检索数据
利用盲XXE的另一种方法是触发一个XML解析错误,其中的错误信息包含你希望检索的敏感数据。如果应用程序在其响应中返回相关的错误信息,那么这种方法就会有效。
你可以使用以下恶意外部DTD触发一个包含/etc/passwd
文件内容的XML解析错误信息:
此DTD执行以下步骤:
定义一个名为
file
的XML参数实体,其中包含/etc/passwd
文件的内容。定义一个名为
eval
的XML参数实体,其中包含另一个名为error
的XML参数实体的动态声明。error
实体将通过加载一个不存在的文件进行评估,该文件的名称包含file
实体的值。使用
eval
实体,这导致error
实体的动态声明被执行。使用
error
实体,以便在尝试加载不存在的文件时评估其值,从而产生一个包含不存在文件名的错误信息,该文件名就是/etc/passwd
文件的内容。
调用恶意的外部DTD将会导致类似如下的错误信息:
LAB
通过重新利用本地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年十大Web黑客技术的第7位。
例如,假设服务器文件系统上的/usr/local/app/schema.dtd
位置有一个DTD文件,并且这个DTD文件定义了一个名为custom_entity
的实体。攻击者可以提交类似以下的一个混合DTD,从而触发一个包含/etc/passwd
文件内容的XML解析错误信息:
该DTD执行以下步骤:
定义一个名为
local_dtd
的XML参数实体,其中包含存在于服务器文件系统上的外部DTD文件的内容。重新定义一个名为
custom_entity
的XML参数实体,该实体已在外部DTD文件中定义。这个实体被重新定义为包含已描述过的基于错误的XXE漏洞利用,用于触发包含/etc/passwd
文件内容的错误信息。使用
local_dtd
实体,以便解释外部DTD,包括重新定义的custom_entity
实体的值。这样就会出现所需的错误信息。
定位一个现有DTD文件以重新利用
由于这种XXE攻击涉及到重新利用服务器文件系统上的现有DTD,因此关键需求是找到一个合适的文件。这其实很简单。因为应用程序会返回由XML解析器抛出的任何错误信息,只需从内部DTD中加载本地DTD文件,你就能够轻松地枚举出这些文件。
例如,使用GNOME桌面环境的Linux系统通常会在/usr/share/yelp/dtd/docbookx.dtd
处有一个DTD文件。你可以通过提交以下XXE有效载荷来测试该文件是否存在,如果该文件丢失,将会引发一个错误:
在测试了一系列常见的DTD文件,找到一个存在的文件之后,你就需要获取该文件的副本并进行检查,以找到一个可以重新定义的实体。由于许多包含DTD文件的常见系统都是开源的,通常可以通过互联网搜索快速获取文件的副本。
LAB
Last updated