首先用dirsearch扫描下目录
由于BUUCTF限制发包量,更改扫描线程
命令:python dirsearch .py -u [url] -e * -t 3 -s 0.2,
扫除/.git泄露
得到两个php文件,kali内githack扫出来但是下载失败了
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;
?>
分析:
第一个文件,flag.php读取flag并赋值给$flag
第二个文件,index.php文件内foreach语句将提交的get和post参数进行变量覆盖,满足if语句后,输出flag
如果想要输出flag,在绕过if语句的情况下还会被执行变量覆盖,如get传参flag=ganyu,在执行第二句foreach语句后变为$flag=$ganyu,由于$ganyu未赋值,则返回值为空
在满足if语句时,exit会输出其值,利用变量覆盖将exit()函数内的参数用$flag覆盖掉就能输出flag了
<?php
$a = "hello";
echo "$a"; //输出hello
$a="world";
echo "$a"; //输出hello
echo "$$a"; //输出word
echo "$a ${$a}"; //输出hello world
echo "$a $hello"; //输出hello world
?>
这里面有三个if语句,尝试第一个exit处。键名不能有flag,而且又要键名为flag的键值等于其中一个键名,进不去这个判断
方法一:
第二个if语句输出的是$yds变量,那么我们就要通过变量覆盖达到$yds=$flag的效果,在第二个foreach语句中,如果要满足$yds=$flag,那么$x=yds,$y=flag,即get传参yds=flag
方法二:
第三个if语句输出的是$is变量,判断条件为$POST['flag'] === 'flag' || $GET['flag'] === 'flag',在第二个foreach语句中,首先是$x=is,$y=flag,带进去就变成了$is=$flag,第二个参数,$x=flag,$y=flag,带进去变成$flag=$flag,即get传参is=flag&flag=flag
关于代码逻辑漏洞导致变量覆盖
一个知识点:PHP中的$$(可变变量),可变变量可以让一个普通的变量值作为这个可变变量的变量名
举个例子:
<?php
$foo="hello";//定义一个变量
$$foo="world";//foo变量值作为这个可变变量的变量名
echo "$foo ${$foo}";//输出hello world
echo "$foo $hello";//输出hello world
?>
有些开发者喜欢选择使用foreach遍历数组(如$_GET,$_POST)来注册变量,也就是上面做的那一题,这样会存在一个变量覆盖漏洞的情况
举个例子:
<?php
$ganyu = false;
foreach($_GET as $key => $value){
$key = $value
}
if ($ganyu){
echo "flag{this_is_ganyus_flag}";}else{
echo "nonono";
}
?>
自己尝试构造payload?
payload:传入?ganyu=1