第二十天php变量覆盖

register_globals导致的变量覆盖问题

  默认在5.4中废弃

register_globals的意思就是注册为全局变量,所以当On的时候,传递过来的值会被直接的注册为全局变量直接使用,而Off的时候,我们需要到特定的数组里去得到它。 C O O K I E , _COOKIE, COOKIE,_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中, v a r 表 示 一 个 名 为 v a r 的 普 通 变 量 , 它 存 储 字 符 串 、 整 数 、 浮 点 等 任 何 值 。 而 var表示一个名为var的普通变量,它存储字符串、整数、浮点等任何值。而 varvar v a r 是 一 个 引 用 变 量 , 用 于 存 储 var是一个引用变量,用于存储 varvar的值。

在我看来就是套娃。 先来个简单的

 $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"<br/>";
      var_dump($a);
      

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
foreach函数遍历数组
.foreach函数有两种语法格式:
·foreach(array as v a l u e ) , 循 环 读 取 数 组 中 元 素 的 值 并 赋 值 给 变 量 value),循环读取数组中元素的值并赋值给变量 value),value。。
·foreach(array as k e y = > key=> key=>value),循环读取数组中元素的键赋值给变量 k e y , 元 素 的 值 赋 值 给 变 量 key,元素的值赋 值给变量 key,value。

$users=array("01"=>"zhangsan","02"=>"1isi","03"=>123);
$colors = array("red","green","blue");
foreach($users as $value) {
    
    
    echo $value . "<br/>";
}
    foreach($colors as $key=>$value) {
    
    
        echo "$key=>$value" . "<br/>";
    }

在这里插入图片描述

来看一个例题
foreach 配合$$

<?php
//可变变量
//$a = 'b';
//$$a = 'hello';
//echo $b;
foreach (array('_GET', '_POST', '_COOKIE') as $item) {
    
      
    foreach ($$item as $k => $v) {
    
     //$$item = $_GET as $k=>$v   这里可变变量 $_GET
        $$k = $v;  //$$k = $XDEBUG_SESSION_START = PHPSTORM   
    }              //数值定义变量 $a = " bihuo.cn"
}

if (!isset($a)) {
    
       
    $a = 100;        //  bihuo.cn
}
if ($a == 'bihuo.cn') {
    
    
    echo 'ok';
}

在这里插入图片描述

举个例子

php
<?php
include'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_GET as $x => $y){
    
     //get传值
    $$x = $$y;  //漏洞在这里  比如输入 yds=flag 相当于 $yds=$flag
}

foreach($_GET as $x => $y){
    
     
    if($_GET['flag'] === $x && $x !== 'flag'){
    
     //判断get传进来的值等不等于flag 如果等于flag则跳过
        exit($handsome);
    }
}

//检测get是否为flag 或者post是否为flag  必须两方都为假  否则输出$yds
//通过这里我们就可以结合前面的来构造 既然要输出$yds所以我们想办法让$flag的值赋值给$yds  
//构造yds=flag GET传输 在经过第一个foreach的时候进行了赋值 等于进行了这样的一个操作$yds=$flag  
//所以这个条件为真就可以输出flag了。
if(!isset($_GET['flag']) && !isset($_POST['flag'])){
    
    
    exit($yds);
    
}
//

//检测POST flag是否为flag  或者get 是否为flag   //至少有一个为真则为真
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 "<br>";
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变量覆盖

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

参考 https://www.secpulse.com/archives/155955.html

猜你喜欢

转载自blog.csdn.net/qq_42096378/article/details/123812609