变量覆盖在ctf中其实不少见了,最近做了几道变量覆盖的题,所以来这里总结一下。
1. $$
导致变量覆盖
在php中,
$a
表示一个变量,我们可以给这个变量赋值。$$a
这种写法称为可变变量,它获取了一个普通变量的值作为这个可变变量的变量名。
例如:
<?php
$a = "_GET";
print_r($a);
echo '</br>';
print_r($$a);
echo '</br>';
print_r($_GET);
?>
当我们通过GET方式传入值时,结果如下图:
$a
的值是'_GET'是没错的,但是$$a
却是一个数组,而且是我们通过GET传入对应的键和值,这就是因为一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。
可以理解为:因为$a
的值是_GET
,所以$$a
现在就是$_GET
.
那么我们如何造成变量覆盖呢?
- 我们可以用foreach来遍历数组,将数组的键名作为变量,键值作为这个变量的值。
例如:
<?php
$a = "_GET";
$bbb = '123';
print_r($$a);
echo '</br>';
foreach($$a as $key=>$value){
$$key = $value;
}
echo '$bbb:'.$bbb;
?>
$bbb
的值本来是'123',但我们通过foreach遍历数组,将通过GET传过来的键值把变量bbb的值覆盖了。
下面是我再ctf中遇到有关变量覆盖的一道题:
<?php
include "flag.php";
$_403 = "Access Denied";
$_200 = "Welcome Admin";
if ($_SERVER["REQUEST_METHOD"] != "POST"){
die("BugsBunnyCTF is here :p…");
}
if ( !isset($_POST["flag"]) ){
die($_403);
}
foreach ($_GET as $key => $value){
$$key = $$value;
}
foreach ($_POST as $key => $value){
$$key = $value;
}
if ( $_POST["flag"] !== $flag ) {
die($_403);
} else {
echo "This is your flag : ". $flag . "\n";
die($_200);
}
?>
题目要求必须通过POST传入flag的值,而且这个值和flag值相同
所以我们首先通过GET传入'_200=flag',将flag
的值覆盖掉_200
的值,然后在通过POST传入'flag=xxx(任意)',这时将会把你输入的值
覆掉flag
,在最后一个if中你POST的flag值就是你输入的值 恒成立,通过else把_200
的值输入就是flag的值,因为前面_200的值已经被flag的值覆盖掉了。
(该题设计的非常巧妙)
2. extract()
导致变量覆盖
例如:
<?php
$a = "aaa";
extract($_GET);
echo $a;
?>
我们通过GET传入a=456,那么变量a的值就会被覆盖成456
但是如果我们写成extract($_GET,EXTR_SKIP);
那就不会覆盖原有的变量