BJDCTF2020 Mark loves cat 1题解


BJDCTF2020 Mark loves cat 1题解

前置知识

php变量覆盖

前一篇博文讲preg_replace /e模式的时候有一个坑涉及到了变量覆盖,当时没有展开讲,这里稍微提一嘴。
可变变量

<?php
$a="b";
$$a="c";
echo $a;
echo $$a;
?>
输出为bc

$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach中出现,如以下的示例代码,使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。请求?name=test 会将$name的值覆盖,变为test。

<?php
$name='thinking';
foreach ($_GET as $key => $value)
  $$key = $value;   //这里进行了覆盖 $$key传入的值是name 传入进入成为$name 所以造成了name外部的变量被覆盖
  var_dump($key);
  var_dump($value);
  var_dump($$key);
echo $name;
//?name=test
//output:string(4) “name”
//string(4) “test”
//string(4) “test”
//test

题目详解

dirsearch扫描目录发现.git,githack下载源码,得到flag.php和index.php
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;

首先分析第一个判断:get参数中的flag值绝对等于某个键名且键名中不能有flag。这个判断并不好绕进去。
分析第二个判断:get的flag和post的flag都为空,会返回$yds,根据变量覆盖漏洞,我们可以构造?yds=flag,这样$x=yds,$y=flag,$$x=$yds=$flag=$$y成功将flag的值赋到yds中输出,得到flag:flag{2cdc1281-db85-4d25-97fd-bf52b8217a02}
分析第三个判断:get型或者post型的flag必须有值且值为flag,且会返回is,那么可以构造?is=flag&flag=flag,这样会进行赋值$is=$flag,$flag=$flag,成功输出flag,而如果flag是以post型flag的值会发生改变从而无法输出。
然后第二个判断和第三个判断互为补集,也就是说无法通过构造的方式达到最后一句,也就是只能利用中间的exit进行输出。

参考:
https://www.cnblogs.com/gtx690/p/13289626.html
https://blog.csdn.net/qq_43622442/article/details/105925473
https://blog.csdn.net/qq_43801002/article/details/105991295


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 !