前言
做[GDOUCTF 2023]受不了一点这道题时想到的一些知识补充
遂记录下来
正文
在本地php环境上进行实验
页面源码
<?php
$flag='Thisisflag';
foreach ($_POST as $key => $value) {
$$key = $value;
}
foreach ($_GET as $key => $value) {
$$key = $$value;
}
print_r(get_defined_vars());
echo "\n";
echo $flag;
为了能够直观的查看各个变量的值,这里使用get_defined_vars()函数返回一个包含所有已定义变量列表的多维数组
foreach()语句能把post/get进去的数组键名作为变量,数组中的键值作为变量的值
打开页面

可以看到目前的全部变量以及flag值的回显
然后我们传入get请求?flag=1

可以发现此时$key->flag,$flag->$value->1,但是flag的值并没有回显,为什么呢?
原因是在get请求的foreach语句中,$$key=$$value,于是我们传进去的参数会变成$flag=$1,但是$1并没有被赋值,所以没有回显
而post请求的foreach语句是$$key=$value
那我们就单独post请求传一个flag=1看看会发生什么

可以看到回显的$flag变成了1
原因是我们传进去的post请求参数会变成$key->flag,$value->1,那么post的foreach执行语句就会变成$flag=1,所以会回显1
现在我们同时get传入?flag=1,post传入1=flag看看会发生什么

很明显这里$flag的值为flag,因为实际foreach语句中为$flag=$1,$1=flag,所以这样子会导致$flag变量被覆盖
现在我们对回显加一个限制
if(isset($_GET['flag'])){
if($_GET['flag']=$flag){
echo $flag;
}
}

再看看get传入1=flag和flag=1的效果

此时$1=$flag='Thisisflag',然后$flag=$1,这样子$flag内的值没有发生改变可以直接匹配’Thisisflag’于是成功回显
总结
变量覆盖的大致思路就是这样,限于本人思维能力,本篇文章叙述表达可能不大清晰555