①foreach+$$可变变量覆盖

  • 引入:

    1
    2
    3
    4
    5
    <?php
    $a = 123;
    $123 = 456;
    echo ${$a} ==> 456
    ?>
  • example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php error_reporting(0); 
show_source(__FILE__); // show_source — 别名 highlight_file() 使用PHP内置的语法高亮器所定义的颜色,打印输出或者返回 filename 文件中语法高亮版本的代码。
include "flag.php";
$_403 = "Access Denied";
$_200 = "Welcome Admin";
if ($_SERVER["REQUEST_METHOD"] != "POST")
die("CISPCTF is here :p...");
if ( !isset($_POST["flag"]) )
die($_403);
foreach ($_GET as $key =&gt; $value){ //通过for循环遍历GET方式传入的参数变量与其值,ex:?_200=flag
$$key = $$value; //如上ex的GET传入,由于使用了可变变量,在此就变为“$_200=$flag”,即覆盖了变量$_200原有的值:“Welcome Admin”,将$flag变量里的值存入了变量$_200
print_r($$key);
echo "------";
print_r($$value);
 }
 
foreach ($_POST as $key =&gt; $value){ //通过for循环遍历post接受的参数,ex:post=>flag=123, 此时
$$key = $value; //如上ex的POST传入,由于使用可变变量,变为$flag=123, 即flag变量原有的值已被覆盖为123,所以下方27行的if语句判断始终全等,无法进入die($_403)语句
}
if ( $_POST["flag"] !== $flag ) // !== 不全等(完全不同) $x !== $y 如果 $x 不等于 $y,或它们类型不相同,则返回 true。
die($_403);
echo "This is your flag : ". $flag . "\n"; //之后走到这里。flag原本值已经被覆盖。,echo出来的flag只是之前覆盖的123
die($_200); //最后走到这里,真正flag的值在14行 被赋值给了变量$_200, 故此条语句打印出了真正的flag。
?>


②extract()函数导致的变量覆盖漏洞

  • 引入:由于未系统学习php,看了一些参考后,对extract()函数的理解还不是很透 彻。。。 但大致可以利用extract($_GET/$_POST)函数来实现将GET或POST的变量名与其对应的值传入;漏洞就发生在若用户传入的变量名与已有变量相同,则用户传入的变量名与其值会将原有的值覆盖造成变量覆盖漏洞。
  • example1:
1
2
3
4
5
6
7
8
9
10
11
$flag = 'xxx';
extract($_GET);//通过extract()函数将将用户通过GET写入的变量名与其对应的值传入。
 
if (isset($gift)) {
$content = trim(file_get_contents($flag));
if ($gift == $content) {//要判断变量gift与content相等,由于extract函数的使用,直接通过get方式传入这两个变量并都赋值为空即可达到变量覆盖以实现相等的目的。
echo 'hctf{…}';
} else {
echo 'Oh..';
}
}

PAYLOAD:?gift=&flag=

  • example2:
1
2
3
4
5
6
7
<?php if ($_SERVER["REQUEST_METHOD"] == “POST”) { ?>
<?php
extract($_POST);
if ($pass == $thepassword_123) {
echo $theflag;
} ?>
//和上一题基本相同,用POST方式传入pass与thepasswod_123变量,并将其赋值为空以覆盖两个变量,使if判断语句为真。

PAYLOAD:POST==>pass=&thepassword_123=



③parse_str(string,array)函数导致的变量覆盖漏洞

  • 引入:该函数用于解析给出的string字符串,并将其注册为变量,之后将变量存入array数组中,若未给出参数array则只注册变量(ex:parse_str(‘a=1&b=2’); echo $a; echo $b ),漏洞就发生在注册变量时不会检查变量是否已经存在,当变量名与已有变量名重复则会造成变量覆盖
  • example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
 
error_reporting(0);
if (empty($_GET['id'])) {
show_source(__FILE__);
die();
} else {
include ('flag.php');
$a = "www.OPENCTF.com";
$id = $_GET['id'];
@parse_str($id);//通过parse_str()函数处理GET方式传入的变量id,会在此时解析变量id所代表的字符串,并直接将字符串中的变量进行注册
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {//此时出现变量a[0],结合上面的parse_str函数,可以利用id来将a[0]变量注册,并根据md5的0e漏洞赋给a[0]一个md5编码后为0e开头的值,这样就可以使if语句判断为真。
echo $flag;
exit;
} else {
exit('其实很简单其实并不难!');
}
}


④import_requests_variables函数导致的变量覆盖漏洞

  • 引入:此函数可以直接将GET/POST/Cookie的参数注册成变量,所以变量覆盖就显而易见了。


⑤小结:

变量覆盖漏洞其实都大同小异,无非就是通过GET或POST传入一些参数,经过上述几个函数的处理,将这些参数解析为了PHP中的变量,若已给出的参数名与已有的变量名相同,则会将变量的值直接覆盖。另外,在实战中,变量覆盖漏洞要考虑的不仅仅是变量覆盖,还要结合后续代码来真正利用起来这个漏洞