代码审计|变量覆盖漏洞

参考链接:http://www.freebuf.com/column/150731.html

0x01 原理

1
用自定义的参数值替换原有变量值的情况称为变量覆盖漏洞

经常导致变量覆盖漏洞场景有:$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。

下面讲解一下CTF的几个例题

0x02 $$ 导致变量覆盖漏洞

代码审计

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
error_reporting(0);
$name=’thinking’;
foreach ($_GET as $key => $value)
$$key = $value;
var_dump($key);
print('<br>');
var_dump($value);
print('<br>');
var_dump($$key);
print('<br>');
echo $name;
?>

$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach中出现,用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的键值作为变量的值。因此就产生了变量覆盖漏洞。请求?name=test 会将$name的值覆盖,变为test。

image

0x03 $$ 例题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php

$_403 = ‘Hello’;
$_200 = ‘HEEEE’;
if ($_SERVER["REQUEST_METHOD"] != “POST”)
die(‘BABABA’);
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);
echo “This is your flag : “. $flag . “\n”;
die($_200);
?>

构造的payload如图:

image

根据这个payload传入两个foreach两个流程就是:

1
2
$_200=$flag //把原来的值给覆盖了
$flag=aaaaaaaaaaa //符合只后的等于post

0x04 extract()函数

extract() 函数从数组中将变量导入到当前的符号表。

http://www.w3school.com.cn/php/func_array_extract.asp

1
2
3
4
5
6
7
8
9
10
11
12
<?php
$flag = ‘xxx’;
extract($_GET);
if (isset($gift)) {
$content = trim(file_get_contents($flag));
if ($gift == $content) {
echo ‘hctf{…}’;
} else {
echo ‘Oh..’;
}
}
?>

代码审计分析

1
题目使用了extract($_GET)接收了GET请求中的数据,并将键名和键值转换为变量名和变量的值,然后再进行两个if 的条件判断,所以可以使用GET提交参数和值,利用extract()对变量进行覆盖,从而满足各个条件。

构造get的payload为

1
?flag=&gift=

0x05 parse_str()函数

parse_str() 函数把查询字符串解析到变量中。

http://www.w3school.com.cn/php/func_string_parse_str.asp

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(‘其实很简单其实并不难!’);
}
}
?>

题目分析

  • 通过parse_str函数可将$a变量覆盖
  • md5函数 0e开头绕过

构造的payload为:

1
?id=a[0]=s878926199a

0x06 import_request_variables()函数

将GET/POST/Cookie变量导入到全局作用域中

bool import_request_variables(string $types[, string $prefix])

types:指定需要导入的变量,可以用’G’,’P’和’C’表示GET,POST和Cookie.
prefix作为变量名的前缀,

1
2
3
4
5
6
7
8
9
10
<?php
$auth='0';
import_request_variable();

if($auth == 1){
echo "private!";
} else{
echo "public";
}
?>

构造payload:

1
?auth=1

会输出private,说明已经成功覆盖原来的0了

总结

没啥好总结的,多看代码多学习多分析.

文章目录
  1. 1. 0x01 原理
  2. 2. 0x02 $$ 导致变量覆盖漏洞
    1. 2.1. 代码审计
  3. 3. 0x03 $$ 例题
  4. 4. 0x04 extract()函数
    1. 4.1. 代码审计分析
  5. 5. 0x05 parse_str()函数
    1. 5.1. 题目分析
  6. 6. 0x06 import_request_variables()函数
  7. 7. 总结
,