BUUCTF [BJDCTF2020]Mark loves cat

打开题目
BUUCTF [BJDCTF2020]Mark loves cat_第1张图片
搜索一番没有任何发现;
dirsearch扫描后发现.git泄露,GitHack.py下载源码:

python GitHack.py http://b77333f7-af9a-4f4a-aad0-b328ef9c8369.node3.buuoj.cn/.git

得到两个php文件,接下来就是代码审计:
flag.php:


$flag = file_get_contents('/flag');

index.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;

分析:

  1. 前两个foreach语句分别将POST参数和GET参数进行变量覆盖,接着是三个if语句,exit()函数退出脚本的同时输出变量,最后一句是输出我们想要的flag。
  2. 首先我们想到的是让脚本执行到最后一句echo $flag;,但即使绕过三个if语句,我们GET传参或者POST传参的flag总会被变量覆盖:如我们GET传参flag=aaa,在第二个foreach语句中变成$flag = $aaa,而$aaa变量没有定义为空,最后的输出就是空
    BUUCTF [BJDCTF2020]Mark loves cat_第2张图片
    同理:我们POST传参flag=aaa,在第一个foreach语句中变成$flag= aaa,flag被覆盖为‘aaa’,最后输出aaa
  3. 由此看来,这样行不通,回过头来前面说到if语句中的exit()函数虽然会退出执行,但也会输出其参数,我们可以利用变量覆盖将exit()函数内的参数用$flag覆盖掉就能输出flag了;
  4. 思路理清了,这里面有三个if语句,其中有两个能利用变量覆盖输出flag,也就是说有两种方法
    一是第二个if语句中可以看到这里是输出的$yds变量,那么我们就要通过变量覆盖达到$yds=$flag的效果,GET传参yds=flag,在第二个foreach语句中,首先是$x=yds,$y=flag,经过$$x = $$y也就变成了$yds=$flag,如下:
    BUUCTF [BJDCTF2020]Mark loves cat_第3张图片
    二是第三个if语句中输出变量$is,判断条件为$_POST['flag'] === 'flag' || $_GET['flag'] === 'flag',这里可以通过满足后面这个条件进行变量覆盖:GET传参is=flag&flag=flag;在第二个foreach语句中,首先是$x=is,$y=flag,带进去就变成了$is=$flag,这就达到了覆盖的目的,而参数中flag=flag只是为了满足if语句
    BUUCTF [BJDCTF2020]Mark loves cat_第4张图片
    考点总结
  5. .git源码泄露;
  6. $$导致变量覆盖漏洞(参考CTF之php变量覆盖漏洞)

你可能感兴趣的:(代码审计,php,web安全,安全)