打开环境,经过一番查找没有发现,后来dirsearch扫描后发现.git
泄露,用git_extract下载得到flag.php和index.php。
flag.php:
$flag = file_get_contents('/flag');
就是读取flag文件内容并赋值给$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,然后是赋值,重要的是后面foreach的用法:
foreach($_POST as $x => $y)意思是,若传值是a=b,那么$x=a,$y=b,GET一样的意思。
- 前两个
foreach
语句分别将POST
参数和GET
参数进行变量覆盖,接着是三个if语句,exit()
函数退出脚本的同时输出变量,最后一句是输出我们想要的flag。 - 首先我们想到的是让脚本执行到最后一句
echo $flag;
,但即使绕过三个if语句,我们GET
传参或者POST
传参的flag总会被变量覆盖:如我们GET
传参flag=aaa,在第二个foreach语句中变成$flag
=$aaa
,而$aaa
变量没有定义为空,最后的输出就是空,同理:我们POST
传参flag=aaa,在第一个foreach语句中变成$flag
= aaa,flag被覆盖为‘aaa’,最后输出aaa - 由此看来,这样行不通,回过头来前面说到if语句中的
exit()
函数虽然会退出执行,但也会输出其参数,我们可以利用变量覆盖将exit()
函数内的参数用$flag
覆盖掉就能输出flag了。 - 思路理清了,这里面有三个if语句,其中有两个能利用变量覆盖输出flag,也就是说有两种方法
(1)第二个if语句中可以看到这里是输出的$yds变量,那么我们就要通过变量覆盖达到$yds=$flag的效果,GET传参yds=flag,在第二个foreach语句中,首先是$x=yds,$y=flag,经过$$x = $$y也就变成了$yds=$flag,这是其一;
(2)第三个if语句中输出变量$is,判断条件为$_POST['flag'] === 'flag' || $_GET['flag'] === 'flag',这里可以通过满足后面这个条件进行变量覆盖:GET传参is=flag&flag=flag;在第二个foreach语句中,首先是$x=is,$y=flag,带进去就变成了$is=$flag,这就达到了覆盖的目的,而参数中flag=flag只是为了满足if语句。
这是个变量覆盖,这两种方法就得到答案。