PHP开发安全建议20则

时间:2009-10-28     作者:smarteng     分类: PHP相关


1.时刻升级你的php版本
  正如其它编程语言一样,PHP的缺陷也会逐渐暴露出来。使用和及时更新最新的php版本将有助于你保证应用程序的安全,高效和稳定。

  2.朦胧的安全根本就不是安全,同时你也不想泄露关于你的网站的信息。以下的建议看似简单,实则在现实生活中很容易被人们忽视。

  确保在你的网站上不展现错误以及关于你网站潜在的信息泄露

  只要在你的产品服务器的php.ini中如下设置即可:display_errors = Off,这样就可以有效防范信息泄露从而给防止黑客知晓关于你的系统结构的的信息。一般的默认设置是display_errors = On.[break]

  3.有安全意识固然不错,但这是远远不够的。

  开发者在面临安全问题的时候一定要有警惕之心。即使你不能单独处理这一问题。只要是应用程序都不可避免的存在大量的安全隐患,只不过是没有爆发出来而已。第三方安全软件有助于找出你没有注意到的安全缺陷。

  作为网站开发人员,手头上一定要有专门的工具帮助你找出应用程序的缺陷。Chorizo可以帮助你自动扫描代码。诸如PHPSecInfo一样的程序帮助你确保配置环境的安全。

  使用诸如此类的扫猫工具并不足以保证100%的安全。尽管如此,仍然是组安全策略中很重要的一部分。一定是使用值得信赖的开发商帮助你构建和维护安全的应用程序。

  4.模糊的安全根本就不是安全,但模糊安全策略必不可少。

  尽管如此,实际当你恰当的使用模糊安全策略的时候也不是为一个好的选择。那些心怀不轨的人实际上就是想把事情弄的很复杂。

  装有机密信息的文件夹和文件不要使用默认的名称。

  不要使用使用艰深晦涩的文件名保证你的应用程序的安全。应该不断的检查网络许可,使用测试工具测试漏洞,利用网络日志监视异常行为。当你设计应用程序和网站的时候,不要让坏人轻易的如愿以偿。文件名和目录名不要使用默认的或是很简单的名称。

  5.php是一个永恒的使命,它要求程序员跳出程序的参数思考问题。仅仅思考“我所设计的东西会按照我的想法一样吗”,你还要思考,“其他人会利用我设计的东西干些什么,我允许他们这样做吗”。以下的安全建议是所有的程序员都应该知道的。

  永远不要相信用户

  这样说也许是有点悲观,但是用户确实就是恶魔。用户只不过是想找出你的程序的缺陷。一旦你自己降低安全要求,并且认为“我只不过是卖点小玩意,客户能有什么能耐呢”,这时候你已经输掉了这场战争。

  过滤入流量,远离出流量(FIEO)

  确实,FIEO是所有的程序员都应该牢记的安全咒语。

  6.在PHP中编写安全程序不仅仅是编写一长串PHP代码就够了。

      许多程序使用数据库或是类似的东西。很多情况下,导致整个应用程序漏洞的就是在构建SQL代码的时候。以下有一条简单的解决之道。

  处理SQL字符串中的数字的时候,一定要计算。

  即使你是在过滤入流量,一个简单而行之有效的安全策略就是把所有的数值都放到SQL报表中。我们以这个代码为例子。

      $myId = filter_var($_GET['id'],FILTER_VALIDATE_INT);
  $sql = 'SELECT * FROM table WHERE id = '.$myId;


  尽管你使用的是PHP 5.2版本内置的php过滤器,你还可以有其它的选择,试一下下面这个:

      $myId = filter_var($_GET['id'],FILTER_VALIDATE_INT );
  $sql = 'SELECT * FROM table WHERE id = '.(int)$myId;


  最后的变量就是变成一个int就会让所有的可以变量远离MySQL.上面的例子故意简化了。在实际情况中,代码更加复杂,产生错误的风险也更大。通过使用最后的计算构建一个精选的报表,这样你就提高了应用程序的安全等级。

  7.当你使用session_regenerate_id()来阻止session固定的时候,最好是将之前的session ID移除。

  实例脚本:

<?php
session_start();
$_SESSION['data'] = time();
session_regenerate_id();
?>


      检测URL以及/tmp路径

sess_82c6980017e100277a63983142fd454c
sess_a4bab88e6dfa6e900ade21e3fbd27a53


      再次检测

sess_984c5230acca90b5a75eddb89bb48354
sess_a4bab88e6dfa6e900ade21e3fbd27a53
sess_82c6980017e100277a63983142fd454c


  然后你可以看到如下情况

      sess_984c5230acca90b5a75eddb89bb48354
  sess_a4bab88e6dfa6e900ade21e3fbd27a53
  sess_82c6980017e100277a63983142fd454c
  sess_dd88c05b724d80b30c90309847f2e919


  这些session仍然很活跃。当重新生成ID的时候移除它们采用如下代码:

<?php
session_start();
$_SESSION['data'] = time();
session_regenerate_id(true);
?>


  如果你正在使用自己的session处理器的话,这可能导致你的destroy callback功能被激活。

  8.使用php安全主题,实际上不止一种方法可以完成任务。在很多情况下,战术的重组可以达到最好的安全效果。我们一直在谈论信息的过滤,我们还需要警惕来自于用户的验证信息。这是在日常的php应用中需要加以注意的。

  确认用户的输入信息

  代码实例:

<?php
$myFile = filter_var($_GET['file'], FILTER_SANITIZE_STRING);
include($myFile);
?>


  点击http://example.com/file.php?file=home.php可能会导致你的脚本包含在你的目前的目录中的文件home.php。但是如果有人请求http://example.com/file.php?file=badcode.php的话,你就会置身于执行代码的危险中,或是你不想执行的代码被执行。

  不要仅仅依靠file_exists(). 因为本地文件并不意味着这是一个正确的文件甚至那根本就不是你的文件。不要让黑客轻易的执行代码。

  为了保证安全,记住一定要过滤和确认:

<?php
// filter
$myFile = filter_var($_GET['file'], FILTER_SANITIZE_STRING);
// Then validate
$valid = array('home.php', 'about.php');
If (!in_array($myFile, $valid)) {
            die('Leave, evil hacker');
}
include($myFile);
?>


  9.有时最简单的也就是最安全的。以下的建议很简单,但是我们很惊讶在现实生活中很少有人理解以及使用。

  不要将敏感信息放于网上

  思考一下下面这个目录结构:

      /htdocs
  /includes
  /images
  /js


  如果你将你的数据库的信任状存储于一个名为db.inc的文件中,然后将其放于这一目录之下,很可能就有人下载这一文件夹名下的信息,只要他们访问http://example.com/includes/db.inc.站点,因为绝大多数的网站服务器并不知道如何处理这一.inc文件,如果有访问请求的话,它们直接被认为是纯文本。后果是可怕的。如果你存储信任状的文件使用的是非.php后缀名的话并且位于你的网络服务器的根目录之下,很可能你的信息正在泄露。

  解决方法很简单。将所有的敏感信息置于网络服务器的根目录之外。现在也有很多专家提倡把绝大多数的php代码放于网络服务器根目录之外。因为php代码不限于同一个限制,你可以在根目录的同一文件层次之下建立一个目录,然后将你的所有的机密信息和代码放在那。

      /phpinc
  /includes
  /htdocs
  /images
  /js


  10.即时所有的事情都做的完美无缺,你构建的php代码仍然存在安全隐患。安全需要永恒的警惕之心。有一件事情你需要时刻保持注意,那就是依赖入流量发送邮件的脚本。许多使用php编写的应用程序使用内置的mail()功能来回应邮件触发的用户流量。

  不要盲目的使用信息发送邮件

  正如我们在其它的关于php的安全建议中谈到的一样,你要确保适当的过滤和确认用户的输入。如果你没有恰当的过滤入流的话,很可能就有人在你没有注意之前使用电子邮件注入以及发送成千的垃圾邮件。

  11.我们都认为用户既是我们开发的程序是天使也是魔鬼。一方面,要是没有用户的话也就不会存在安全问题了。再者,要是没有用户,我们就没有必要开发应用程序了。因此我们认为不能让客户流失。这就是说必须要他们知晓相关的安全问题。我们可以采取如下措施:

  最少权限原则

  只给予用户最低层次的许可

  这是最基本的编程原则,在绝大多数的Unix中可以看到。处理unix中的用户和资源的时候,用户清楚无误的知道自己的访问权限。用户的访问权限只足以访问最基本的资源。我们在开发应用程序的时候也可以借鉴这一概念。

  许多现代的php构架都使用了这一概念或是授权访问控制。在Zend构架中,授权是由Zend_Auth处理,但是访问控制是由另外一个Zend_Acl处理的。

  不管你使用哪一个结构,一个好的安全策略就是在网页或图片上设置访问限制。不管什么时候,要将用户的访问权限限制到最低程度。

  12.我们已经谈论过过滤,确认以及再次谈论过滤。过滤应用程序的输入是一个很重要的概念,它应该先于很多安全策略之前执行。尽管如此,即使你执行了良好的过滤制度和确认制度,这并不意味这你可以高枕无忧了。在编程的整个过程都必须谨记安全问题。

  过滤输入让一些程序开发人员产生了安全错觉。他们武断的认为既然已经采取了过滤措施,就没有必要担心安全问题了。在一些简单的程序中可能确实是没有什么问题,但是在一些复杂的程序中就不然了,你要知道使用这些输入是干什么的。在用户在eval()命令使用输入的时候的时候就可以看出。以下是一些建议:

  在使用eval()之前认真思考一下

  通过在eval()中使用用户输入参数,你很可能给恶意用户访问服务器开了后门。即使你的操作界面仅仅允许他们选择已经设置好的界面,使用你的脚本哄骗,那么你的脚本很可能就会被别有用心之人用来即时执行罪恶的行当。

  尽量少使用eval()。当你不得不使用的时候,一定要保证过滤和确认输入的有效性。如果还有其它选择的话,就使用另外的方法。

  13.安全要常记心中,而不是偶然为之。它和代码一样为你的程序增彩。尽管如此,你还需要实时监控你的产品环境。那就是我们为什么要选择正确的工具的原因。我之前提过PHPSecInfo,这一工具足以保证自身的安全。

  PHPSecInfo可以有效的监视你的产品环境。

  PHPSecInfo提供与phpinfo()相似的功能,它可以提供关于php环境的安全信息,并且提供改进建议。但是它并不是安全开发技术的替代品,也不提供任何形式的代码或是程序监测,但是在多层次安全策略中很有效。

  对于安全建议,单靠自身是远远不够的。恰当的组合可以发挥很大的效用。

  14.几乎所有的应用程序都在使用网络技术的后端用户上运行php,因为这是前期工作。许多开发人员在php安全上苦思冥想,却不注意前期的开发工作。以下就是关于在构建HTML和java脚本时应该考虑的一些问题。

  任何位于cookie中的数据都可能被其他人看到——将其降低到最低限度

  现在的网络很令人失望,坏人太多。他们等着你的应用程序的信息泄露然后利用这些敏感信息获取利益。评估应用程序安全的时候一定要综合考虑。当你在前期输入数据的时候,这尤其重要。

  15.作为开发者,很多人做事很混乱。我曾经做过无数的项目,很多人将大量的测试文件到处乱放。(info.php, test.php, doMe.php,等等)。这些信息如果被别有用心者获得,就会泄露关于系统的有价值的信息。

  建议

  不要忘记清除临时的系统诊断文件

  你很可能会感到后悔,如果你花费大量的时间保护你的应用程序而忘记了info.php,test.php 中的“quick piece of code”可能会泄露关于你的系统的危险信息。不要助纣为戾。

  16保证你现在使用的构架实时更新

  如果你是在一台临时的机器上工作的话,这尤其重要。考虑谁来维持折合站点是很重要的,如果安全补丁是由第三方文件提供的。

  一般来说,这些站点位于一个共享的主机站点上,这就意味着提供商负责维护php,数据库系统,网络服务器等等的实时更新——但是他们很可能不会维护你所安装的构架。

  使用构架是一个不错的主意——并不是因为它省去了你很多麻烦,更因为它会及时处理相关的安全隐患。

  另一方面还意味着这些构架中的网络安全问题都会被记录下来——也就是说黑客可以寻找出仍在使用的构建的老版本,然后轻易的发动攻击。

  现在很多站点使用老掉牙的文件——只是因为没有专人负责升级。即使不是你为超额服务器流量买单——实际上你的邮箱收到了大量的垃圾邮件。

  17.应用程序的安全不是一个所有的措施都失效的情况。不是事后可以处理的。正如我们前面所提到,应用程序的安全没有一个万全的解决之道。安全贯穿于设计的初始,代码编写,测试以及产品成功开发之后的整个阶段。

  一位著名的php安全专家曾经给出如下的安全建议:

  ● 安全是一种措施,而不是特征。

  ● 安全必须与投入之间寻求平衡

  ● 安全需要与实用性之间寻找到平衡点

  ● 安全是设计的一部分

  以上对于徘徊在安全设计织之外的人是很好的建议。

  18.当你允许用户上传文件,这就意味着你的系统有风险。要限制允许上传的文件类型。不要依赖黑名单策略。

  举个例子来说,黑名单不允许上传.php文件,这确实是一个不赖的主意,要是有人上传.htaccess文件的话,黑名单就失去了效用。将恶意代码置于这一文件之中实际上黑名单在客观上帮助了那些居心叵测之人。

  AddType应用程序/x-httpd-php .php .htm

  它们现在可以上传任何形式的带有php代码的.htm文件,然后就在你的系统内胡作非为。

  例如:

<?php
echo system("locate config");
?>


  很有可能上述代码会提供攻击者位于服务器之内的配置名。这种攻击的可能性是永恒的,仅仅是因为你的服务器未保护的一个上传。

  一定要重视文件上传的问题,确保使用白名单政策。确保上传文件的形式是所允许的文件类型。有几种方式可以实现这一目的,最简单的就是检查上传文件的扩展名。这样那些不适当的文件扩展名就会被排除。但是,这不是最安全的做法。

  要想实现更加安全的监管,检查PECL扩展名,FileInfo。FileInfo检查 文件的内容并且根据特定的字节顺序猜测内容形式。将FileInfo与白名单政策一起使用的话会在文件上传的时候更加安全的保护你的系统。

  19.有时最好的应用程序安全策略就是不要断开服务器与网络的的连接。但是现实生活中是行不通的。考虑安全问题的时候,软件和硬件同样重要。

  最安全的应用程序就是不与外界相联系

  正如前面所说,这在现实中根本就行不通。但是你可以选择那些服务器可以与外部网络相联系,那些需要布置在防火墙之内。此外还要考虑,防火墙之外的服务器如何与之内的服务器沟通的问题。

  Session劫持,XSS, 和XSRF都是开发者必须面临的挑战,我并不是危言耸听。确实在很多情况下,这就意味着末日。对于绝大多数的黑客来说,很容易突破的技术数据库。开发人员面临的最严重的问题就是程序被劫持,数据库受到威胁,以及用户的信任信息在网上的传播。

  一个简单的方法就是把数据库服务器移到防火墙之后,这样就可以限制对其的访问。一旦你认识这一问题,你发现还有其它的方法帮助你保护整个系统。

  20.最后一条建议,推荐读如下科目:

      《Essential PHP Security》

      《Pro PHP Security》

      《Professional PHP5 Security》

      《php|architect's Guide to PHP Security》