变量覆盖漏洞

0x00
前段时间做题遇到很多关于变量覆盖漏洞的问题,想好好整理一下,把之前做题和看文章中遇到过的好好研究一下,简单记录一下。
变量覆盖漏洞就是用自定义的参数值替换原有的变量值导致漏洞的产生。导致这种漏洞的本质是函数使用不当。
部分示例代码来自:<传送门>
0x01
经常引起变量覆盖漏洞的原因(函数)有:开启了全局变量注册、$$使用不当、extract()函数使用不当、parse_str()函数使用不当、import_request_variables()函数使用不当.

0x02 全局变量覆盖
全局变量覆盖的关键是register_globals
register_globals的意思就是注册为全局变量。当register_globals=On,用户传递的值会被直接的注册为全局变量直接使用;register_globals==Off,需要到特定的数组里去得到它。也就是说为on的时候,变量可以从各个地方传来,当为off的时候,不会有问题。
示例代码:

1
2
3
4
5
6
7
<?php
echo "Register_globals: ".(int)ini_get("register_globals")."<br/>";

if ($auth){
echo "private!";
}
?>

当register_globals=On提交?auth=1时,$auth会被赋值为1。
ps:如果已经对$auth变量赋了初始值,即使提交也不会覆盖。

0x03 \$\$导致的变量覆盖漏洞
\$\$导致变量覆盖的问题在于foreach() foreach遍历数组中的值,然后将获取到的数组键名作为变量,数组中的键值作为变量的值,所以就产生了变量覆盖漏洞。
示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
<?php
// ?name=test
// output:string(4) “name” string(4) “test” string(4) “test” test
$name=’thinking’;
foreach ($_GET as $key => $value)
$$key = $value;
var_dump($key);
var_dump($value);
var_dump($$key);

echo $name;
?>

例题(iscc2018)

代码的大体意思是包含flag.php 满足三个条件才可以得到flag .,两个foreach对$$key的处理是不一样的,满足条件会打印出flag。可以看到有两个foreach,中间代码会将$flag值覆盖掉
我们的思路是把$flag的值赋值给$_200或$_403 然后利用die(200)或die(403)打印出来。
payload: GET: ?_200=flag
POST: flag=aaaaaaaaaaaaaaa
0x04 extract()函数导致的变量覆盖漏洞
extract() 该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
函数语法: extract(array,extract_rules,prefix)

例题:(bugku)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$flag='xxx';
extract($_GET);
if(isset($shiyan))
{
$content=trim(file_get_contents($flag));
if($shiyan==$content)
{
echo'flag{xxx}';
}
else
{
echo'Oh.no';
}
}
?>

用extract($_GET) 接收了GET请求中的数据,并将键名和键值转换为变量名和变量的值,然后再进行两个if 的条件判断,所以可以使用GET提交参数和值,利用extract()对变量进行覆盖,从而满足各个条件。
payload:?flag=&shiyan=
这里是把 flag和shiyan的值都覆盖为空,从而相等。

0X05 parse_str()函数导致的变量覆盖漏洞
parse_str() 函数把查询字符串解析到变量中。 如果未设置 array 参数,由该函数设置的变量将覆盖已存在的同名变量。
语法:parse_str(string,array)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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);
if ($a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)) {
echo $flag;
} else {
exit(‘其实很简单其实并不难!’);
}
}
?>

分析代码:
get提交id。利用parse_str()函数处理,然后if比较,\$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)满足 则打印flag
这里利用的是 php弱语言特性,需要一个MD5后以0e开头的才能够返回true。
这样的值很多,提交:?id=a[0]=240610708
与parse_str()类似的函数还有mb_parse_str()

0x06 import_request_variables()函数导致的变量覆盖漏洞
import_request_variables — 将 GET/POST/Cookie 变量导入到全局作用域中
示例代码:

1
2
3
4
5
6
7
8
9
<?php
$auth = '0';
import_request_variables('G');
if($auth == 1){
echo "private!";
}else{
echo "public!";
}
?>

import_request_variables(‘G’)指定导入GET请求中的变量,从而导致变量覆盖。

查阅资料,也参考了很多大佬的文章,还要多多积累,CTF中积累小的代码审计,才能审计cms,还要不断地理解。

-------------本文结束有错指正哦!-------------