PHP安全之register_globals

一、register_globals = Off 和 register_globals = On的区别

register_globals是php.ini里的一个配置,这个配置影响到php如何接收传递过来的参数.

register_globals的值可以设置为:On或者Off,我们举一段代码来分别描述它们的不同。

 

 

[php] view plain copy
 
  1. <form action='' method='get'>  
  2.   
  3. <input type='text' name='username' value='alex' >  
  4.   
  5. <input type='submit' name='sub' value='sub'>  
  6.   
  7. </form>  
  8.   
  9. <?php  
  10.   
  11. echo 'username::',$username;  
  12.   
  13. echo '<br>sub::',$sub;  
  14.   
  15. echo '<br>GET::';  
  16.   
  17. print_r($_GET);  
  18.   
  19. ?>  

 

当register_globals = On的时候,程序运行提交输出结果为:

 

[php] view plain copy
 
  1. username::alex  
  2.   
  3. sub::sub  
  4.   
  5. array ( [username] => alex [sub] => sub )   

 

当register_globals = Off的时候,程序运行提交输出结果为:

 

 

[php] view plain copy
 
  1. username::  
  2.   
  3. sub::  
  4.   
  5. array ( [username] => alex [sub] => sub )   

 

通过测试结果,显而易见:register_globals的意思就是注册为全局变量,所以当On的时候,传递过来的值会被直接的注册为全局变量直接使用,而Off的时候,我们需要到特定的数组里去得到它。

二、为什么推荐register_globals = Off?

1.PHP 4.2.0 版开始配置文件中 register_globals 的默认值从 on 改为 off 了,虽然你可以设置它为On,但是当你无法控制服务器的时候,你的代码的兼容性就成为一个大问题,所以,你最好从现在就开始用Off的风格开始编程。

2.当 register_globals 打开以后,各种变量都被注入代码,例如来自 HTML 表单的请求变量。再加上 PHP 在使用变量之前是无需进行初始化的,这就使得更容易写出不安全的代码。当打开时,人们使用变量时确实不知道变量是哪里来的,只能想当然。但是 register_globals 的关闭改变了这种代码内部变量和客户端发送的变量混杂在一起的糟糕情况。例子来源手册

 

[php] view plain copy
 
  1. <?php  
  2.   
  3. // 当用户合法的时候,赋值  
  4.   
  5. $authorized = true  
  6.   
  7.   
  8. if (authenticated_user()) {  
  9.   
  10. $authorized=true;  
  11.   
  12. }  
  13.   
  14.   
  15. // 由于并没有事先把 $authorized 初始化为 false,  
  16.   
  17. // 当 register_globals 打开时,可能通过GET auth.php?authorized=1 来定义该变量值  
  18.   
  19. // 所以任何人都可以绕过身份验证  
  20.   
  21. if ($authorized) {      
  22.   
  23. include"/highly/sensitive/data.php";  
  24.   
  25. }  
  26.   
  27. ?>   

 

当 register_globals = on 的时候,上面的代码就会有危险了。如果是 off,$authorized 就不能通过如 URL 请求等方式来改变,这样就好多了,尽管初始化变量是一个良好的编程习惯。比如说,如果在上面的代码执行之前加入 $authorized = false 的话,无论 register_globals 是 on 还是 off 都可以,因为用户状态被初始化为未经认证。

 

 

三、如果需要在一台关闭了 register_globals 的共享主机上运行一些旧式程序而该程序需要此选项打开时怎么办?

本例模拟 register_globals On。如果改变了配置文件中的 variables_order 选项,则考虑对 $superglobals 作出相应的改动。

 

[php] view plain copy
 
  1. <?php// Emulate register_globals on  
  2.   
  3. if (!ini_get('register_globals')) {  
  4.   
  5. $superglobals= array($_SERVER,$_ENV,$_FILES,$_COOKIE,$_POST,$_GET);  
  6.   
  7. if (isset($_SESSION)) {  
  8.   
  9. array_unshift($superglobals,$_SESSION);  
  10.   
  11. }  
  12.   
  13. foreach ($superglobals as $superglobal) {  
  14.   
  15. extract($superglobal,EXTR_SKIP);      
  16.   
  17. }  
  18.   
  19. }  
  20.   
  21. ?>  

 

四、如果需要在一些打开了register_globals选项的主机上但想消除安全隐患,该怎么办?

本例模拟 register_globals Off。要记住此代码应在脚本最开头的地方调用。如果使用了会话机制,则在 session_start() 之后调用。

[php] view plain copy
 
  1. <?php// Emulate register_globals off  
  2.   
  3. functionun register_GLOBALS(){  
  4.   
  5. if (!ini_get('register_globals')) {  
  6.   
  7. return;      
  8.   
  9. }  
  10.   
  11. // Might want to change this perhaps to a nicer error  
  12.   
  13. if (isset($_REQUEST['GLOBALS']) || isset($_FILES['GLOBALS'])) {  
  14.   
  15. die('GLOBALS overwrite attempt detected');      
  16.   
  17. }  
  18.   
  19. // Variables that shouldn't be unset      
  20.   
  21. $noUnset= array('GLOBALS','_GET','_POST','_COOKIE','_REQUEST','_SERVER','_ENV','_FILES');  
  22.   
  23. $input=array_merge($_GET,$_POST,$_COOKIE,$_SERVER,$_ENV,$_FILES,isset($_SESSION) &&is_array($_SESSION) ?$_SESSION: array());  
  24.   
  25. foreach ($input as $k=>$v) {  
  26.   
  27. if (!in_array($k,$noUnset) && isset($GLOBALS[$k])) {  
  28.   
  29. unset($GLOBALS[$k]);          
  30.   
  31. }      
  32.   
  33. }  
  34.   
  35. }  
  36.   
  37.   
  38. unregister_GLOBALS();  
  39.   
  40. ?>  

 

 
posted @ 2016-05-03 10:17  南无  阅读(301)  评论(0编辑  收藏  举报