题目地址:https://buuoj.cn/challenges
解题思路
第一步:进入题目,没有任何提示,使用dirsearch扫描出了/.git路径,使用GitHack获取/.git下的内容,发现了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;
第二步:代码审计
- foreach将as前的参数获取的键名赋值给x,值赋值给y
- 第一个判断:当get获取的键名有flag且键名不等于flag时输出handsome,从逻辑判断这里永远为假,进不去。
- 第二个判断:当get没有获取到的flag参数且post没有获取到的flag参数时,输出is
- 第三个判断:当post获取到的flag参数是flag字符串或get获取到的flag参数是flag字符串时,输出is
第三步:获取flag
- 通过第一步获取到的源码最后一段发现要输出$flag这个变量才能显示flag
- 按f12查看源码发现卡在了第二判断,由于我们没有通过get或post传入flag参数
- 如果我们传入flag=xx参数,foreach函数就会改变$flag的值,使最后一句不能正常输出flag的值
- 使用变量覆盖漏洞,不传入flag,但是将
$yds
的值修改为$flag
,这样输出yds时,就会输出flag的值,构造payload:?yds=flag
,在通过foreach($_GET as $x => $y){ $$x = $$y; }
时,$x=yds,$y=flag;而$$x=$yds,$$y=$flag,这样$yds=$flag,输出yds时就会输出flag的值
- 思路二:传入flag参数且修改is参数,payload:
?is=flag&flag=flag