对PHP_SELF保持警惕,过滤后再使用

  1. <html> 
  2.     <body> 
  3.         <?php 
  4.             if (isset($_REQUEST['submitted']) && $_REQUEST['submitted'] == '1') { 
  5.                 echo "Form submitted!"; 
  6.             } 
  7.         ?> 
  8.         <form action="<?php echo $_SERVER['PHP_SELF']; ?>"> 
  9.             <input type="hidden" name="submitted" value="1" /> 
  10.             <input type="submit" value="Submit!" /> 
  11.         </form> 
  12.     </body> 
  13. </html> 

上面这段看似准确无误的代码,但是暗藏着危险。让我们将其保存为 test.php ,然后放到 PHP 环境中使用

test.php/%22%3E%3Cscript%3Ealert('xss')%3C/script%3E%3Cfoo

访问,会发现弹出个 Javascript 的 alert -- 这很明显又是个 XSS 的注入漏洞 。究其原因,发现是在

  1. echo $_SERVER['PHP_SELF'];  

这条语句上直接输出了未过滤的值。追根数源,我们看下 PHP 手册的描述

'PHP_SELF'

The filename of the currently executing script, relative to the document root. For instance, $_SERVER['PHP_SELF'] in a script at the address http://example.com/test.php/foo.bar would be /test.php/foo.bar. The __FILE__ constant contains the full path and filename of the current (i.e. included) file.If PHP is running as a command-line processor this variable contains the script name since PHP 4.3.0. Previously it was not available. 

原因很明确了,原来是 $SERVER['PHPSELF'] 虽然「看起来」是服务器提供的环境变量,但这的确和 $POST 与 $GET 一样,是可以被用户更改的。

其它类似的变量有很多,比如 $_COOKIE 等(如果用户想「把玩」他们的 cookie,那我们也是没有办法)。

解决方案很简单,使用 strip_tags 、 htmlentities 等此类函数过滤或者转义。

  1. echo htmlentities($_SERVER['PHP_SELF']);  

上述的例子让我们需要时刻保持谨慎 coding 的心态。Chris Shiflett 在他的 Blog 总结的相当直白 ,防止 XSS 的两个基本的安全思想就是

Filter input和Escape output

我将上面翻译成 「过滤输入,转义输出」

转载请注明:代码家园 » 对PHP_SELF保持警惕,过滤后再使用

评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)