变量覆盖漏洞

变量覆盖及危害

变量覆盖(Dynamic Variable Evaluation)是指变量未被初始化,我
们自定义的参数值可以替换程序原有的变量值。

通常结合程序的其它漏洞实现完整的攻击,比如文件上传页面,覆盖掉原来白名单的列表,导致任意文件上传;用户注册页面控制没覆盖的未初始化变量导致SQL。

常见的变量覆盖的特征

在这里插入图片描述

变量初始化变量

bianli.php

<?php
    $a = 1;
    foreach (array('_COOKIE','_POST','_GET') as $_request){
        foreach ($$_request as $_key => $_value){
            $$_key = addslashes($_value);
        }
    }
    echo $a;
    //echo $_key;
    //echo $$_key;

这里我们先分析下代码原理,当我们在url中没有传入a参数时,它只是单纯输出a变量的值,当我们传入a参数时,这时执行循环,将$a的变量的值赋值给$key,此时$key=$a,而$$key的值就等于a传入的参数值,达到一个变量覆盖的作用。
在这里插入图片描述
将上面注释掉的两行代码取消
在这里插入图片描述
第一个123是原本$a的值,a是指$key的值,123是指$$key的值。这里为了让小伙伴更好地理解代码,其实上面的代码意思就是将$a和对应的值存进一个数组中并取名为变量request,然后双变量request指向的就是变量a,在第二次每次循环中都把变量a赋给变量key,把变量a的值赋给value。

注:造成以上效果必须满足一个条件就是php.ini文件中的register_globals的值必须为Off

extract()变量覆盖

int extract ( $array , extract_rules,prefix )
$array 关联的数组,受第二个和第三个参数的影响。
extract_rules 对待非法/数字和冲突的键名的方法将根据取出标记
prefix 仅在第二个参数特殊时需要,添加前缀

第一种

<?php
    //第一种情况
    $password = 'pwd';
    $arr = array(
        'username' => 'username',
        'password' => 'password',
        'rand' => 'rand'
    );
    extract($arr,EXTR_PREFIX_SAME,'pwd');
    echo "$username.$password.$rand";
    echo "." . $pwd_password;

运行效果如下图所示
在这里插入图片描述
extract() 检查每个键名看是否可以作为一个合法的变量名,同时也检查和符号表中已有的变量名的冲突。对待非法/数字和冲突的键名的方法将根据 extract_type 参数决定。

这里关键是extract($arr,EXTR_PREFIX_SAME,'pwd');这个代码,这个代码原本的意思是倘若变量名有冲突,在变量名前加上前缀 prefix。现在$pwd_passwordpassword添加前缀后才能等于关联数组内password对应的值,这样就达到了一个变量覆盖的作用。

第二种

<?php
	$password = 'pwd';
    $arr = array(
        'username' => 'username',
        'password' => 'password',
        'rand' => 'rand'
    );
    extract($arr,EXTR_OVERWRITE);
    echo "$username.$password.$rand";

运行效果如下
在这里插入图片描述
这里不同的是extract($arr,EXTR_OVERWRITE);,如果发现有冲突,则直接覆盖并输出关联数组中的对应的键的值。

第三种

<?php
	$password = 'pwd';
    $arr = array(
        'username' => 'username',
        'password' => 'password',
        'rand' => 'rand'
    );
    extract($arr,EXTR_IF_EXISTS);
    echo $password;

运行效果图
在这里插入图片描述
常见的危险函数

参数描述
EXTR_OVERWRITE默认。如果有冲突,则覆盖已有的变量。
EXTR_SKIP如果有冲突,不覆盖已有的变量。(忽略数组中同名的元素)
EXTR_PREFIX_SAME如果有冲突,在变量名前加上前缀 prefix。自 PHP 4.0.5 起,这也包括了对数字索引的处理
EXTR_PREFIX_ALL给所有变量名加上前缀 prefix(第三个参数)
EXTR_PREFIX_INVALID仅在非法或数字变量名前加上前缀 prefix。本标记是 PHP 4.0.5 新加的。
EXTR_IF_EXISTS仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。可以用在已经定义了一组合法的变量,然后要从一个数组例如 $_REQUEST 中提取值覆盖这些变量的场合。本标记是 PHP 4.2.0 新加的。
EXTR_PREFIX_IF_EXISTS仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。本标记是 PHP 4.2.0 新加的。
EXTR_REFS将变量作为引用提取。这有力地表明了导入的变量仍然引用了 var_array 参数的值。可以单独使用这个标志或者在 extract_type 中用 OR 与其它任何标志结合使用。本标记是 PHP 4.3.0 新加的。

parse_str()变量覆盖

void parse_str ( string $encoded_string [, array &$result ] )
$encoded_string 输入的字符串
$result 变量将会以数组元素的形式存入到这个数组,作为替代

<?php
    $a = 'a';
    parse_str($a = 'b');
    echo $a;

运行效果
在这里插入图片描述
这里这个函数和前一个不同,这个是直接在函数中对变量的值进行替换,它不会先去检测变量的值是否存在冲突

import_request_variables函数

bool import_request_variables ( string $types [, string $prefix ] )
$type 指定需要导入的变量。可以用字母‘G’、‘P’和‘C’分别表示 GET、POST 和 Cookie
$prefix 变量名前缀

<?php
    $a = '0';
    import_request_variables('G');
    if($a != 0){
        echo 'success';
    }else{
        echo 'fail';
    }

在这里插入图片描述
这个函数将 GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局变量,那么此函数就很有用。

这里给出一个别人大佬在CTF中见到的例子,以下是它的链接
https://www.cnblogs.com/xhds/p/12587249.html#_label3

修复方案

  1. 在php.ini文件中设置register_globals=OFF
  2. 使用原始变量数组,如$_POST,$_GET等数组变量进行操作
  3. 不使用foreach语句来遍历$_GET变量,而改用[(index)]来指定
  4. 验证变量是否存在,注册变量前先判断变量是否存在
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

平凡的学者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值