PHP变量覆盖--超详细
后台-插件-广告管理-内容页头部广告(手机) |
变量覆盖漏洞
看下面这个例子:
$a='hello'; $b='world'; $$a=$b; echo($hello);- 1
- 2
- 3
- 4
最后的输出结果为world
这里先是定义了a,b两个变量,分别赋值hello和world。接着,$$a表示将变量a的值变成一个变量即$hello,然后将变量b的值赋给它,最后输出world。
所以在源码中看到$$可以想到变量覆盖漏洞。
同时,还有一些函数也会出现变量覆盖,这里我们就先看以下foreach函数
foreach函数会遍历数组,然后将键名与键值分别赋值给后面的变量,这样就容易产生变量覆盖漏洞
- 1
- 2
- 3
这里我传入参数?a=hello,那么就相当于我传入了一组键值对,键名为a,键值为hello(即$key=a,$value=hello),接着执行$$key=$value,这里就会变成$hello=hello
其他一些函数其实大同小异,在题目中遇到了再做了解吧
下面来看一道题目
[BJDCTF2020]Mark loves cat
进入靶机,看到如下网页
到处浏览,点一点,感觉没什么东西,页面源代码也没什么有用的,想用dirsearch扫一下文件路径,但是一直报429,弄了好久没法解决,就不耐烦看了眼大佬的wp,发现有git源码泄露,就用githack还原了一下,还原出两个文件,分别是flag.php与index.php
都打开看一下
<?php $flag = file_get_contents('/flag'); //获取flag文件flag.php
- 1
- 2
- 3
<?php include 'flag.php'; //包含flag.php文件 $yds = "dog"; $is = "cat"; $handsome = 'yds'; foreach($_POST as $x => $y){ //遍历post传入的数据,然后将值赋给以值命名的变量 $$x = $y; } foreach($_GET as $x => $y){ //遍历get传入的数据,然后使分别以变量名与值命名的变量相等 $$x = $$y; } foreach($_GET as $x => $y){ //遍历get传入的数据 if($_GET['flag'] === $x && $x !== 'flag'){ //传入的flag参数的值要等于某一个键值名并且这个键值名不能为flag exit($handsome); //满足条件,退出并输出$handsome } } if(!isset($_GET['flag']) && !isset($_POST['flag'])){ //判断get与post是否传参flag exit($yds); //如果都没传入flag,则退出并输出$yds } if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){ //post或get有一个传入flag参数并且值为flag即可满足条件 exit($is); //满足条件,退出并输出$is } echo "the flag is: ".$flag; //输出flagindex.php(去掉其他源代码之后)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
一开始学完刚看到这题目,直接蒙了,然后就乖乖去学习大佬的wp了
一共有三种解法,分别对应了上面的三个exit()
第一种输出$handsome
要想得到flag,就要使$handsome=$flag,那么就能够想到前面的foreach函数
foreach($_GET as $x => $y){ $$x = $$y; }- 1
- 2
- 3
他能使flag覆盖handsome这个变量,那么payload就是?handsome=flag,当我们尝试着传入参数后,发现,并没有给我们flag,而是给我们返回了dog,也就是说它执行了下面这句,那么我们还需要传flag参数
if(!isset($_GET['flag']) && !isset($_POST['flag'])){ exit($yds); }- 1
- 2
- 3
而传入flag参数后就必然逃不过下面这个if,传入的flag参数的值要等于某一个键值名并且这个键值名不能为flag
if($_GET['flag'] === $x && $x !== 'flag'){ exit($handsome); }- 1
- 2
- 3
既然前面已经传了一个handsome参数,那我们就构造?handsome=flag&flag=handsome,输入后,发现如下直接返回了flag,也就是说,代码退出了并输出了$handsome
应该有同学会想,我将两个参数换个位置变为?flag=handsome&handsome=flag可不可以,尝试一下你就会发现,输出yds而不是flag,因为在一开始foreach循环的时候,flag就被handsome覆盖掉了,后面flag就一直是yds。
第二种输出$yds
这种方法就简单了,我们在上面直接传?handsome=flag的时候发现,页面只返回了dog,也就是说在不传入flag的情况下会输出$yds
if(!isset($_GET['flag']) && !isset($_POST['flag'])){ exit($yds); }- 1
- 2
- 3
那么我们就可以直接利用变量覆盖将$flag覆盖$yds,构造?yds=flag得到flag
第三种输出$is
满足传入的flag参数等于'flag'就行,也就是说直接传flag=flag
if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){ exit($is); }- 1
- 2
- 3
构造?is=flag&flag=flag得到flag
到这里这道题就结束了,但是我一直在想最后的echo能不能被利用输出flag,发现并不能,无论你怎么构造,都逃不过那三个exit(),最后的echo就是来迷惑你的,想让我这样的新手不去想变量覆盖。。。。
好了变量覆盖的学习就到这里。
参考:[BJDCTF2020]Mark loves cat(3种解法)
1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。
在线投稿:投稿 站长QQ:1888636
后台-插件-广告管理-内容页尾部广告(手机) |