Bookmark and Share

Lee's 程序人生

HTML CSS Javascript XML AJAX ATLAS C# C++ 数据结构 软件工程 设计模式 asp.net Java 数字图象处理 Sql 数据库
  博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

编写安全的 PHP 代码

Posted on 2007-08-08 05:13  analyzer  阅读(208)  评论(0编辑  收藏  举报

前言:有的时候会想写一篇自己对PHP 代码的安全编写的看法,如果你或许正想了解一些关于
PHP 代码编写环境中可以遇见的安全隐患,如果你觉得你可能可以靠这篇文档回忆起以前编写PHP
环境中忽视的问题,那么你停在这一页,这篇文档就是期望试图来说清,我们究竟有一些什么样的
忽视会被人利用呢?

变量

    变量是 PHP 本身运行的基础,说到变量,我们则需要再注意一下 PHP.ini 里对我们变量会造成
一些其他影响的设置。

    register_globals

    这个设置在  PHP   4.2.0 开始默认为  Off,它的作用是把用户提交的  GET、POST、COOKIE、
SESSION 、 FILES   等 变 量 转 成 全 局 变 量 , 例 如 当 你 在 浏 览 器 提 交 类 似
http://localhost/register.php?text=test
    那么,除了本身的  GET      的变量外,会增加一个 $text=’test’;  这样的变量,但是原来变量
已经被定义的话,则不会覆盖。

    magic_quotes_gpc

    这个设置默认为  ON ,它中文的名字叫魔法引用,它的作用是把用户提交的  GET 、POST 、
 COOKIE  等变量用类似addslashes 的方式在  ’、”、\       这三个和  NULL   字符前加上  \   字符进行转
 义。

    当然,在  PHP.ini 里不免有其他的设置可以影响到我们的变量。由于很多原因,我们在这里暂
列出这两个关键性的设置。register_globals     和  magic_quotes_gpc 在  PHP 4.3.9 以后的默认设置都是
很安全的,但是由于编写程序的种种方便,编写者总是会以其他函数的方式来实现  register_globals
这样的功能。而下面,我们就要讲到的是函数,这对我们的变量的影响也是很大的。

函数

    extract

    这个函数在  PHP   3.0.7 到现在都存在,一般的时候程序员会用它来在  register_globals          为  OFF
的时候进行类似的操作,而这个函数在不同的参数的时候有着不同的能力,而一般最主要要注意的
是下面两个。
    EXTR_OVERWRITE    如果有冲突,覆盖已有的变量。
    EXTR_SKIP  如果有冲突,不覆盖已有的变量。

    第一个参数在手册上写得很清楚了,如果变量已存在,则会覆盖原来的变量,而下面的一个则
是不会覆盖原有变量,但是如果提交的变量本不存在,则会产生一个全局变量,在这里我们需要注
意的是,当在这里不指明这函数的第二个变量的时候,默认使用 EXTR_OVERWRITE


大家可以写下面这样一小段代码来进行测试。

代码片段 
    <?PHP 
    $str = 1; 
   @extract($_GET,EXTR_OVERWRITE); 
    echo $str; 
    ?  

    把它存为  test.PHP,然后在浏览器里提交http://localhost/test.php?str=atest,则会打印出  atest  这
样的字串,自然,为了显示出这样的效果,我把  extract                放到了  str  赋值的后面,而实际上,只要
你像这样使用这个函数,它是无论如何都会影响到  GLOBALS                    里的数据,例如  FILES、SESSION、
GET、POST、COOKIE     等  PHP 本身创建的变量值。

    urldecode

    这个函数用来返回 URL  编码后的字符串,这个在 PHP 编写环境中是较为常见的,但是滥用它
可能会影响magic_quotes_gpc 本身的操作,大家可以写入如下的代码进行测试。

代码片段 
    <?PHP 
    echo urldecode($_GET['url']); 
    ?  

    我们在开启  magic_quotes_gpc  的情况以下面的  Url     去浏览这个页面:
http://localhost/urldecode.php?url=%2527

    你会发现,页面打印的是一个单引号,在这个时候, magic_quotes_gpc 本身的作用已经被彻
底的破坏了,因为,我们提交的字符到服务器的时候实际上是 %27,再被 urldecode 的时候则会还
原成单引号,在这里,我们可以提交任意  magic_quotes_gpc 本身处理过的单引号,双引号,反斜
杠以及 NULL 字符。

    substr

    这个函数用来返回处理变量的一部分,这个函数在PHP 编程环境中应用很广,可是,在不仔细
处理的时候,它也可能会遗留下本来不被期望的字符。

    例如下面这样的代码:

代码片段 
    <?PHP 
    echo substr($_GET['text'], 1);  
    ?  

    从我们提交的  text   里第二位开始取值,那么,如果我们提交http://localhost/text.php?text=abcd
时候,则会被截取成  bcd,而当我们提交http://localhost/text.php?text=’bcd的时候,则会显示  ’bcd,
反斜杠被 substr 给去掉了。

    这样的情况是因为 substr 在我们提交  ’bcd          的时候实际操作的是  \’bcd,所以会把  \        给截取,
然后留下  ’bcd   这样的字符串。

    由于很多原因,关于函数方面可能的疏忽没有办法在这里一一列出,而后要讲的是代码安全编
写的建议,代码的安全是一个整体,即使我把所有已知可能疏忽的函数一一列出,也无法解决一个
代码的安全,下面要说到的是较为安全的编码规范。

编码规范

    不管我们鉴于还是不鉴于 extract 或是 register_globals 这样的情况,被建议的编写方式
是,所有使用到的全局变量必须被初始化。

    数字,数组,字符串的初始化应当不同,否则可能会在下面引用的时候导致不必要的错误,建
议的初始化方式类似下面这样。

    数字的初始化:$str = 0;
    字符串的初始化:$str = ‘’;
    数组的初始化:$str = array(‘’);

    为什么不会把所以变量全初始为空呢?因为这样的话,类似foreach 操作的时候,则会得到一个
错误,而按我们上面这样的初始化的话,则不会发生类似这样的问题。

    而这些变量的初始化建议在使用这个变量前几行进行初始化,且最好不要把初始化放在 if 语句
之中进行。如果不这样做会有什么后果呢,看一下本期后面的一篇文章《PHP  程序安全性的八百种
死法 之 未初始化的变量》你就知道啦。?

我要啦免费统计