其实顾名思义,变量覆盖漏洞就是原先服务端定义好的变量,原设定不能由用户随意更改、查看的变量,可以被我们用一些方法去更改、读取。
先贴一下之前做的有关php可变变量的复习和foreach导致变量覆盖的试验
得再了解一下php可变变量
由下面的试验,应该是如果同时存在$a和
简单来说:
1-$hello存在,$$a的值变成$hello的值
2-$hello不存在,$hello的值变成$$a的值
- $a='hello';
- $$a=1; //这里再定义$$a,$$a=1应该就相当于$hello=1,可以看到$$a和$hello输出是一样的
- echo $$a.'
'; - echo $hello.'
'; - ------------------------------
- 1
- 1
- $a='hello';
- $$a='2';
- $hello='3';
- echo $a;
- echo $$a;
- echo $hello;
- --------------------------------
- hello
- 3
- 3
- //之后我突然发现,如果$$a='2';$hello='3'这两行代码交换了位置,echo $hello会输出2
- $a='hello';
- $$a='2';
- #$hello='3';
- echo $a;
- echo $$a;
- echo $hello;
- --------------------------------
- hello
- 2
- 2
另外说一下${}这样的,${}会获取内部的值并把它当作一个变量来解析
- $a='1';
- $$a='2';
- echo $1; //这么写会报错的,数字不能做变量名
- echo ${1}; //这样写就和上面的利用规则一样了
- --------------------------------------
- 报错 2
简单复习一下可变函数,当我们在一个变量后面加上括号,php就会尝试把它当作一个函数来解析
- function test(){
- echo "hello";
- }
- $a='test';
- $a();
- -------------------------------------
- hello
那么,下面这个foreach到底是怎么完成变量覆盖的?
这里我发现foreach遍历的时候它内部的$x这种带一个$符号的就是我们get传的键值对,带两个$$的是这俩分别对应的值
- foreach($_GET as $x => $y){
- $$x = $$y;
- }
-
- $hello='123';
-
- $flag="flag{hhh}";
-
- $_GET=array();
- $_GET['hello']="flag";
- var_dump($_GET);
- echo $hello.'';
- echo $$flag.'';
- foreach($_GET as $x => $y){
- echo $x.'<--$x_first_$y-->'.$y.'';
- echo $$x.'<--$$x_second_$$y-->'.$$y.'';
- echo $hello.'';
- $$x = $$y;
- echo $hello.'';
- }
- echo $hello.'';
- -----------------------------------------
- C:\wamp64\www\test\ppp.php:12:
- array (size=1)
- 'hello' => string 'flag' (length=4)
- 123
-
- hello<--$x_first_$y-->flag
- 123<--$$x_second_$$y-->flag{hhh}
- 123
- flag{hhh}
- flag{hhh}
extract
- $a = "1";
- $my_array = array("a" => "Cat","b" => "Dog", "c" => "Horse");
- extract($my_array);
- echo "\$a = $a; \$b = $b; \$c = $c";
- ?>
-
- 运行结果:$a = Cat; $b = Dog; $c = Horse
例题
- $test=*****;
- extract($_GET);
- if(isset($gift)){
- $content=trim($test);
- if($gift==$content){
- echo 'flag is:'.$flag;
- }else{
- echo 'nonono';
- }
- }
- parse_str("name=gyy&&age=60"); // test=123&gift=123
- echo $name."
"; - echo $age;
- ?>
-
- 输出了gyy和60
$$
不仅仅是函数会导致变量覆盖,有些特殊符号的特殊搭配也会引起变量覆盖漏洞,比如$$。
$$ 导致的变量覆盖问题在CTF代码审计题目中经常在foreach中出现,如以下的示例代码,使用foreach来遍历数组中的值,然后再将获取到的数组键名作为变量,数组中的值作为变量的值,因此就产生了变量覆盖漏洞。请求?name=test 会将$name的值覆盖,变为test。
做一下规律总结,foreach里面
$$x = $y; 我们可以以类似flag=xxx的形式把任意变量覆盖为xxx
除了这两种利用方式,别的好像是造成不了实际影响的,可以这么理解,上面说过
- $a='hello';
- $$a=1; //这里再定义$$a,$$a=1应该就相当于$hello=1,可以看到$$a和$hello输出是一样的
或许可以这么记,虽然不知道啥原理,左边的得借助$$进到这个变量的$xxx才能进行传值,右边的不需要进到$xxx
1-当$$x=$y,事先有$x=xxx,
$$x=$xxx=$y,覆盖
2-当
3-当$x=$$y,左边进不到$xxx,没法传值
- $a = 1;
- foreach(array('_COOKIE','_POST','_GET') as $_request) { // $_request只是一个普通的变量名
- foreach($$_request as $_key=>$_value)
- {$$_key=addslashes($_value);}}
- echo $a;
- ?>