1 函数extract()变量覆盖
extract()函数的作用是从数组中导入变量到当前符号表中,检查每个键是否是有效的变量名。它还检查与符号表中现有变量是否冲突。为了防止发生变量覆盖,在使用的时候需要将flags设置为EXTR_SKIP,以免将已有变量覆盖。
<?php
extract($_REQUEST); //使用extract造成变量覆盖
if(authenticated_user()){ //认证用户是否登录
$authorized = true;
}
?>
当用户提交的参数中包含authorized = true时,在执行authenticated_user()步骤之前,extract()函数从$_REQUEST中解析到authorized并设置全局变量,它的值被设置为true。此时,用户在无须通过校验的情况下可直接向下执行,绕过了校验逻辑、造成任意越权访问。
为了避免全局变量覆盖的发生,应尽量不使用extract()函数接收客户端参数。下面是修复后的代码。
<?php
$username = $_POST['username'];
$password = $_POST['password'];
if(authentcated_user($username,$password)){ //认证用户是否登录
$authorized = true;
}
2 函数import_request_variables()变量覆盖
import_request_variables()函数的作用是导入GET/POST/Cookie变量进入全局范围。如果在PHP配置中禁用了register_globals,但是又希望导入一些全局变量,可能会用到import_request_variables()函数。
<?php
import_request_variables("gp"); //导入GET或POST中的变量造成变量覆盖
if(authenticated_user()){ //认证用户是否登录
$authorized = true;
}
?>
当用户提交的参数中包含authorized=true时,在执行authenticated_user()步骤之前,import_request_variables解析GET或POST中包含的authorized参数,并且设置为true。此时,用户在无须通过校验的情况下可直接向下执行,绕过了校验逻辑,造成任意越权访问。
为了避免全局变量覆盖的发生,应尽量不使用上述方式接收客户端参数。
修复代码如下:
<?php
$username = $_POST['username'];
$password = $_POST['password'];
if(authentcated_user($username,$password)){ //认证用户是否登录
$authorized = true;
}
3 函数parse_str()变量覆盖
parse_str()函数用于解析客户端以x-www-form-urlencoded编码格式的字符串到PHP变量中。该函数有指定输出变量和不指定输出变量两种使用方式。
下面是parse_str()的两种使用方式。
<?php
$str = "first=value&arr[]=foo+bar&arr[]=baz";
//第一种:当指定输出变量时
parse_str($str, $output);
echo $output['first']; //value
echo "n";
echo $output['arr'][0]; //foo bar
echo "n";
echo $output['arr'][1]; //baz
echo "n";
//第二种:当不指定输出变量时
parse_str($str);
echo $first; //value
echo "n";
echo $arr[0]; //foo bar
echo "n";
echo $arr[1]; //baz
?>
在不指定输出变量的情况下,极易出现变量覆盖,影响正常业务逻辑,例如以下形式。
<?php
parse_str($GLOBALS['HTTP_RAW_POST_DATA']); //获取POST中的变量造成变量覆盖
if(authenticated_user()){ //认证用户是否登录
$authorized = true;
}
当用户在提交的参数中直接提交authorized=true时,parse_str()函数通过解析POST中的authorized并且将值设置为true。此时,无法执行if条件内部语句即可将authorized的值设置为true,就跳过了用户验证逻辑,造成任意登录。
为了避免全局变量覆盖的发生,应尽量使用指定输出变量的方式。
修复后的代码:
<?php
parse_str($_POST,$output);
if(authenticated_user($output['username'],$output['password'])){
//认证用户是否登录
$authorized = true;
}
诚招志同道合的徒弟,还一片教育的净土。
打败你的不是学费,而是“回去再考虑考虑”。
如果时光倒退10年,你最想做的事是什么?
毫无疑问,那是你错过了选择,有的时候选择比努力更重要!
优质的价格、增值的服务、技术的天堂,打造你的“黑客”世界。
学习内容:Web渗透测试、CTF、二进制、逆向、代码审计、免杀等。深耕红蓝紫对抗、漏洞分析与挖掘、红队武器开发、二进制安全、免杀等。
学成:加入团队做项目、内推、护网、就业。
方式:手把手教会,一对一咨询。
非诚勿扰,觉得有缘,请扫描下方二维码加浪师父:
原文始发于微信公众号(船山信安):原创 | PHP变量安全之函数变量覆盖
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论