[BJDCTF2020]Mark loves cat | 四种解法 (新解法:强类型比较绕过)

题目地址:https://buuoj.cn/challenges#[BJDCTF2020]Mark%20loves%20cat
image

image

首先打开网站看到的是一个个人博客,这种常规的 类似实战题目 先扫描目录看看

路径扫描

image
没错这真的是我的字典,就7个路径,哈哈哈,还在收集啊

git泄露

看到了一个 .git 泄露
image
用了俩工具测试,无任何有用信息,工具名称在图片里:GitHackGit_Extract
这俩工具 一个获取文件,一个获取 .git 文件, 哈哈哈,今天才发现,我是真的菜
image
flag.php 是存在的 ,不过只能确定 /flag 在哪里
image
image

429 Too Many Requests

烦死了,没法用现成的工具扫路径
python .\dirsearch.py -e * -u http://f3398cf1-ffb4-443e-a439-a264a65e4d5d.node4.buuoj.cn:81/ -t 1 --timeout=2 -x 400,403,404,500,503,429
果然看大佬的文章才能学到知识啊, 我自己设置了 -t 1 但是没啥用,还是报429 ,看看人家大佬设置 --timeout=2 就可以了,真强

人傻了,那个index.php 后面是有代码的

image
然后分析分析代码:


<?php

include 'flag.php';
print_r($flag);

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

foreach($_POST as $x => $y){  // $键 = $值的值
    $$x = $y;  
    
}

foreach($_GET as $x => $y){
    $$x = $$y;// $handsome = flag的值  --->   $handsome = $flag  --> $x=handsome & $y=flag
}

 // 需要不满足以下几个条件
foreach($_GET as $x => $y){
    if($_GET['flag'] === $x && $x !== 'flag'){  //不能同时 flag的值等于某个键名,那个键值又是flag
        exit($handsome);
    }
}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){// 不能同时  GET 和 POST 都没设置 flag
    exit($yds);
}

if($_POST['flag'] === 'flag'  || $_GET['flag'] === 'flag'){// 任意都不能满足 flag === 'flag'
    exit($is);
}

echo "the flag is: ".$flag;

这个东西真的是需要自己去慢慢看的,慢慢看才能学到东西,主要涉及的就是可变变量
经过大佬的点拨,我悟了

这个题我是没找到 绕过判断不提前结束 ,而又不改变flag值的情况下到达最后的echo。但是别忘了 “exit” 也是一种输出啊!这里虽然输出的不是$flag变量,但是我们有变量覆盖漏洞啊!
https://blog.csdn.net/qq_43622442/article/details/105925473
那么情况就很明确了,污染 exit 语句的参数 , 不过后来证明,大佬说的是不对的,哈哈哈。

解法1:exit($handsome);

首先进入条件:
if($_GET['flag'] === $x && $x !== 'flag'){ //不能同时 flag的值等于某个键名,那个键名又是flag, 就是 flag=a && a!=flag啊,这样就能进了 ?flag=(不是flag)&(不是flag)=xxx
image
进入条件十分简单:?flag=a&a=flag 即可
函数判断到 a=flag 的时候, $_GET['flag'] === $x && $x !== 'flag' --> a === a && a !== 'flag' 这就进来了 true && true 就进来了, 然后 exit($handsome);
因为要 exit($handsome); 那么我们要做的就是 让 $handsome = $flag get 条件的处理如下:

foreach($_GET as $x => $y){
    $$x = $$y;// $handsome = flag的值  --->   $handsome = $flag  --> $x=handsome & $y=flag
}

$$x = $$y而我们要的结果是$handsome = $flag那么特简单 让 $x=handsome 和 $y=flag即可
payload1:http://127.0.0.1/CTF/?handsome=flag&flag=b&b=flag
payload2:http://127.0.0.1/CTF/?handsome=flag&flag=handsome(看师傅们的评论看到的)

解法2:exit($yds);

想要进入这个 exit语句的话,先来看看条件
if(!isset($_GET['flag']) && !isset($_POST['flag'])){// 不能同时 GET 和 POST都没设置 flag
哦,GET,POST 都不设置flag就进去了啊
payload:http://127.0.0.1/CTF/?yds=flag 好简单,这题目
image

解法3:exit($is);

这个也比较简单:
进入条件: if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){// 任意都不能满足 flag === 'flag'
flag=flag
payload: http://f3398cf1-ffb4-443e-a439-a264a65e4d5d.node4.buuoj.cn:81?is=flag&flag=flag
image

解法4:echo "the flag is: ".$flag;

强类型比较绕过
我在尝试的时候发现有个问题:

  1. 正常情况
    http://127.0.0.1/CTF/?a=flag&flag=a 这里触发了 if($_GET['flag'] === $x && $x !== 'flag'){ //不能同时 $_GET['flag'] 的值等于某个键名,那个键名又不是flag 这个条件,进入了 exit($handsome);里面了,这很好理解的。函数遍历 a=flag 的时候, $_GET['flag'] === $x && $x !== 'flag' --> a === a && a !== 'flag' 这就进来了 true && true 就进来了, 然后 exit($handsome);
    image
  2. 不正常的情况
    http://127.0.0.1/CTF/?1=flag&flag=1 这是啥情况呢,按道理来说跟上面一样啊,这里触发了 if($_GET['flag'] === $x && $x !== 'flag'){ //不能同时 $_GET['flag'] 的值等于某个键名,那个键名又不是flag 这个条件,进入了 exit($handsome);里面了,这很好理解的。函数遍历 1=flag 的时候, $_GET['flag'] === $x && $x !== 'flag' --> 1 === 1 && 1 !== 'flag' 这就进来了 true && true 就进来了, 然后 exit($handsome);但是事实不是这样的,我估计是涉及到 字符串和数字的问题,都打印出来看看。
    image
    打印代码:
foreach($_GET as $x => $y){
    echo "</br>foreach :".'</br>';
    echo '$_GET[\'flag\'] :';
    var_dump($_GET['flag']).'</br>';
    echo '$x :';
    var_dump($x).'</br>';
    echo '$_GET[\'flag\'] === $x :';
    var_dump($_GET['flag'] === $x).'</br>';
    echo '$x !== \'flag\' :';
    var_dump($x !== 'flag').'</br>';
    if($_GET['flag'] === $x && $x !== 'flag'){  //不能同时 1 === 1 && 1 !== 'flag' flag的值等于某个键名,键名又不是flag
        exit($handsome);
    }
}

image

果然啊,get 传参数的时候,如果传入1,默认:做为键:类型是 int; 做为值,类型是 string

问题就这这里了:$_GET['flag'] === $x : 如果传入 a=flag&flag=a 那么 判断 a=flag 的时候 $_GET['flag']a, &xa,完全相等 进入if条件, 而如果传入 1=flag&flag=1 那么判断 1=flag的时候 $_GET['flag'](string)1&x(int)1 不完全相等,无法进入if条件,进而绕过

这样就绕过好了,满足了大佬说的几句话,不会改变 flag 而且不会提前结束,具体其他几个循环自己打印看看就行。

这个题我是没找到 绕过判断不提前结束 ,而又不改变flag值的情况下到达最后的echo。


还有一个可能的解法(没试,不知道),传入 $$$xx=$$xx,或者 更多的 $$$$$$$x=$xx, 来绕过 变量覆盖,这里记一下,变量覆盖可以多次递归(没实验过)

posted @ 2022-02-22 11:46  Nestar  阅读(1964)  评论(0编辑  收藏  举报