register_globals导致的变量覆盖问题
默认在5.4中废弃
register_globals的意思就是注册为全局变量,所以当On的时候,传递过来的值会被直接的注册为全局变量直接使用,而Off的时候,我们需要到特定的数组里去得到它。COOKIE,_COOKIE,C?OOKIE,_POST,$_GET全部会注册为全局变量.

漏洞原理
变量覆盖是指可以用自己的传参值代替程序原有的变量值。
漏洞寻找
例如下面的函数或者语法使用不当时就会出现漏洞。
$$
extract()
parse_str()
import_request_variables()
mb_parse_str
register_globals
$$
原理
$$产生的漏洞主要是因为foreach遍历数组的值,然后将获取的数组键名作为变量,数组中的值作为变量的值。
在这先简单介绍一下foreach和$$。
foreach循环只适用于数组,并用于遍历数组中的每个键/值对。
<
?php
$colors = array("red","green","blue","yellow");
foreach ($colors as $value) {
echo "$value n";
}
?>
输出:red
green
blue
yellow
$$这里举个例子
在PHP中PHP变量,var表示一个名为var的普通变量,它存储字符串、整数、浮点等任何值。而var表示一个名为var的普通变量,它存储字符串、整数、浮点等任何值。而var表示一个名为var的普通变量,它存储字符串、整数、浮点等任何值。而var是一个引用变量,用于存储var是一个引用变量,用于存储var是一个引用变量,用于存储var的值。
在我看来就是套娃。 先来个简单的
$a = "b";
$$a = "123"
echo $b;
结果 : 123
<?php
$var = "ee";
$$var = "eeknight";
echo $var ;
echo "n";
echo $$var;
echo "n";
echo "$ee";
?>
输出:ee
eeknight
eeknight
php中的数组
通过数组可以一次性定义一组变量.
数组有多个元素组成,每个元素相当于一个变量
每一个元素是一个"键值对" (key => value) , 键是变量的名字, 值是变量中的数据.
<?php
$a[1] = "bihuo";
$a[2] = "lisi";
$a[3] = 123;
print_r($a);
echo" ";
var_dump($a);


foreach函数遍历数组
.foreach函数有两种语法格式:
·foreach(array asvalue),循环读取数组中元素的值并赋值给变量value),循环读取数组中元素的值并赋值给变量value),循环读取数组中元素的值并赋值给变量value。。
·foreach(array askey=>key=>key=>value),循环读取数组中元素的键赋值给变量key,元素的值赋值给变量key,元素的值赋 值给变量key,元素的值赋值给变量value。
$users=array("01"=>"zhangsan","02"=>"1isi","03"=>123);
$colors = array("red","green","blue");
foreach($users as $value) {
echo $value . " ";
}
foreach($colors as $key=>$value) {
echo "$key=>$value" . " ";
}

来看一个例题
foreach 配合$$
<?php
foreach (array('_GET', '_POST', '_COOKIE') as $item) {
foreach ($$item as $k => $v) {
$$k = $v;
}
}
if (!isset($a)) {
$a = 100;
}
if ($a == 'bihuo.cn') {
echo 'ok';
}

举个例子
php
<?php
include'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_GET as $x => $y){
$$x = $$y;
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){
exit($handsome);
}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}
echo "the flag is: ".$flag;
?>
parse_str() 解析字符串 目前用的很多
将字符串中的值注册为全局变量表中的变量
默认的话 就是将str中的值注册为全局变量
例如
<?php
$str = $_GET['str'];
parse_str($str);
if ($name === 'bihuo.cn'){
echo 'success';
}
else{
echo 'fail';
}


<?php
$str = $_GET['str'];
parse_str($str);
if ($name === 'bihuo.cn' && $age === '18'){
echo 'success';
}
else{
echo 'fail';
}
parse_str能够解析多个变量

需要%26编码


在看这一个例题
<?php error_reporting(0);
$a = "www.bihuo.cn";
$id = $_GET['id'];
@parse_str($id);
var_dump($a);
if ($a[0] != "QNKCDZO" && md5($a[0]) == md5("QNKCDZO")) {
echo "success";
} else {
exit("failure");
}

传一个数组 md5弱类型

注意点 将变量导入到指定的数组中



extract() 转换独立的变量
这里先分析函数,再分析漏洞。
extract()
原理
extract()函数可以将数组中的元素转换切多个独立的变量
他使用数组键名作为变量名,使用数组值作为变量值
例如 这是本来的使用
<?php
$a ="roda";
$my_array = array("a" => "123","b" => "456", "c" => "567");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";
echo " ";
echo "$a";



extract变量覆盖
这个变量的名字正好跟这个数组里边的这个元素的键重名
<?php
$a = "eeknight";
$my_array = array("a" => "C","b" => "T", "c" => "F");
extract($my_array);
echo "\$a = $a; \$b = $b; \$c = $c";
?>
输出:
$a = C; $b = T; $c = F




如果要避免覆盖原有的变量,可以在extract()函数中加上EXTR_PREFIX SAME参数。
·这样如果有冲突,就在变量名前加上前缀,当然前缀也需要由我们来指定。



这里先举个例子
<?php
$a="echo 'eeknight';";
echo $a;
echo "n";
eval($a);
?>
输出:
echo 'eeknight';
eeknight
在上面双引号包裹了单引号,然后通过eval去利用他,就可以直接输出单引号里的东西了。
为什么要说这个东西,因为当你单引号里的东西可以被利用,是不是就可以写什么执行什么了。
怎么利用呢,这时候刚才介绍的extract就发挥作用了。
把上面的例子简单改一下
<?php
$a="echo 'eeknight';";
extract($_GET);
eval($a);
?>

例题
<?php $flag = 'flag.php';
extract($_GET);
if (isset($ceshi)) {
$content = trim(file_get_contents($flag));
if ($ceshi == $content) {
echo 'flag{bihuo.cn}';
} else {
echo 'Oh.no';
}
} ?>

<?php
include 'flag.php';
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
extract($_POST);
if ($pass == $bihuo){
echo 'now this is the flag:{bihuo.cn}';
}
}

<?php
include 'flag.php';
$status_403 = 'denied';
$status_200 = 'ok';
if ($_SERVER['REQUEST_METHOD'] == 'POST'){
if (!isset($_POST['flag'])){
exit($status_403);
}
foreach ($_GET as $k=>$v){
$$k = $$v;
}
foreach ($_POST as $k=>$v){
$$k = $v;
}
if ($_POST['flag'] !== $flag){
exit($status_403);
}
echo 'now the flag is '.$flag;
}

import_request_variables变量覆盖



参考
(编辑:威海站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|