>백엔드 개발 >PHP 튜토리얼 >教您如何应用PHP开发出安全的应用程序_PHP

教您如何应用PHP开发出安全的应用程序_PHP

WBOY
WBOY원래의
2016-06-01 12:31:491014검색

PHP是一种跨平台的服务器端的嵌入式脚本语言。它大量地借用C,Java和Perl语言的语法, 并耦合PHP自己的特性,使WEB开发者能够快速地写出动态产生页面。最新版本PHP5.01支持目前绝大多数数据库(Mysql、PostgreSQL、Oracle,、DB2、Sybase等)。还有一点,PHP是完全免费的,不用花钱,你可以从PHP官方站点(http: //www.php.net)自由下载。PHP拓展了WEB Server的功能,实现了Web最佳服务的后端延展界面,见图-1。



图-1 PHP拓展了WEB Server的功能
  PHP全称Professional HyperText PreProcessor。以最新的PHP5.01为例支持它的WEB服务器有:Apache, Microsoft Internet information Sereve, Microsoft Personal web Server, AOL server, Netscape Enterprise 等等。

  PHP是一种功能强大的语言和解释器,无论是作为模块方式包含到web服务器里安装的还是作为单独的CGI程序程序安装的,都能访问文件、执行命令或者在服务器上打开链接。而这些特性都使得PHP运行时带来安全问题。

虽然PH P是特意设计成一种比用Perl或C语言所编写的CGI程序要安全的语言,但正确使用编译时和运行中的一些配置选项以及恰当的应用编码将会保证其运行的安全性。由于我们可以在很多不同的方面利用 PHP,因此它有很多设置选项来控制其行为。

  一组庞大的可选参数能够保证您可以将 PHP 用于许多不同的目的,但这同时也意味着这些参数和服务端配置的组合会带来一些安全问题。 PHP 的配置与其代码相比,有着同样的灵活性。PHP 可以用来建立完整的服务端应用程序,拥有所有外壳用户的权限;它也可以在被严格控制的环境下用作一个简单的服务端包含,仅承担很小的风险。您如何建立该环境,以及其安全性如何,在很大程度上取决于 PHP 的开发者。 注:本文所有操作在Red Hat Linux 9.0下完成。

  一、 安全从头开始

  在编译PHP之前,首先确保操作系统的版本是最新的,必要的补丁程序必须安装过。安装编译PHP过程中要注意的4个问题:

  1、 使用Apachetoolbox整合Apache,PHP,Mysql 目前最好的web建站黄金组合是Linux Apache Mysql PHP, 但是在实际工作过程中需要分别下载,安装,配置apache,php和mysql,并且需要根据具体情况修改apache的httpd.conf, php的php.ini还有mysql的配置文件,如果你还需要提供ssl功能,那还得下载正确的ssl apache模块,并定制它的.ini文件等,其中的任何步骤出现问题都会导致网站不能正确运行。

  想一次完全配置成功,即使对于一个经验丰富的Linux网络管理员也比较困难。Apache Toolbox是用shell脚本写成的。Apache Toolbox可以很很方便的使你定制你的apache按您的要求在Apache支持的52个第三方的软件包以及36个模块中选择。

  定制的过程完全用菜单驱动,而且都有简单的说明。所有的组件都是用源代码方式安装,在安装过程中,如果发现RPM包有问题,它还会用wget去重新下载新的可用的组件包。相信对那些网络管理员是一个有用的工具。

  Apache Toolbox 可以在GUN命令行下安装,也可以在X窗口下安装,为了方便读者阅读本文以在X窗口下安装为例。在www.apachetoolbox.com下载最新的apachetoolbox安装包。包括apache2.0,mysql3.23.51,php4.3,Python 2.0、 PostgresSQLv7.1等常用建站软件和APC (一种为PHP提供Cache的模块),Apache Toolbox Apache Toolbox提供了一个简单的编译Apache方法,能让你很容易地安装Apache、 SSL,PHP, ZendOptimizer, mod_auth-nds,mod-dynvhost,WebDAV,mod_fastcgi,mod_gzip,mod_layout,mod_throttle,mod_accessref, mod_auth_sys, mod_bandwidth, mod_auth_ldap, mod_perl, openldap.等等以及最新的支持PNG格式的 gd 库。它支持完全的菜单界面。


图-2 Apachetoolbox安装界面

  2、按照Apache 模块安装当 PHP 被用作 Apache 的模块时,它将继承 Apache 的用户权限(典型情况为用户"nobody")。 这将对安全及授权机制产生一些冲击。

  例如,如果您使用 PHP 来访问数据库,除非数据库本身有内建的访问控制,否则您将使得数据库能够被用户"nobody"访问。这意味着恶意的脚本能够访问并修改数据库,甚至不需要用户名和密码。网络黑客无意中访问到了数据库管理员的 WEB 页面并通过这里删除所有的数据库是完全有可能发生的。

  您可以利用 Apache 的认证机制来防止这些的发生,或者也可以利用 LDAP 或 .htaccess 文件等来设计您自己的访问模式,并将这些代码包含为您 PHP 脚本的一部分。

  通常,一旦安全机制建立并使得 PHP 的用于(在这种情况下,为 Apache 用户)仅为此承担很小的风险时,我们发现 PHP 此时被禁止往用户目录写入任何文件,或者还有可能被禁止访问和更改数据库。无论往防止的对象中写入文件的好坏以及进入的数据库事务的好坏,其安全性都是同等的。

  在这个时候,一个频繁出现的安全错误是给 Apache root 权限,或者用其它方法提升 Apache 的能力。

  给 Apache 用户赋予 root 权限是及其危险的,而且有可能会连累整个系统。因此,进行 sudo、chroot,或者以 root 账号运行等操作不应该考虑让那些非安全专家来执行。 还有一些更简单的情况。您可以使用 open_basedir 来控制和限制 PHP 能够使用的目录。您还可以建立 Apache 的专用区域,以将所有基于 WEB 的活动都限制到非用户、系统和文件。

  3、把PHP解析器放在Web目录外

  一种安全性非常高的方法是把 PHP 解析程序放置到 WEB 文件目录树以外的某个地方,例如,放置到 /usr/local/bin。这种做法唯一的弊病就是您现在需要在所有含有 PHP 标记符文件的第一行添加类似于以下的内容:

<ccid_code></ccid_code>#!/usr/local/bin/php


  您需要使得这些文件成为可执行文件。也就是说,像对待任何其它 CGI 脚本一样来对待它们。这些 CGI 脚本可能是用 Perl、sh 或者任何其它使用的 #! shell-escape 机制来启动它们自身的脚本语言来编写的。要使这个方法中 PHP 能够正确处理 PATH_INFO 和 PATH_TRANSLATED 信息,在编译 PHP 解析器时必须使用配置参数--enable-discard-path。下面是一个能作为CGI程序运行的PHP脚的例子。

<ccid_code></ccid_code>#!/usr/local/bin/phpecho 

"This is a  my small  program"


  4、最后将PHP请升级为最新稳定版本:4.3.8。

  在PHP 4.1中,添加了一组特殊数据以访问外部数据。这些数组可以在任何范围内调用,这使得外部数据的访问更方便。在PHP 4.3.8中,register_globals被默认关闭以鼓励使用这些数组以避免无经验的开发者编写出不安全的PHP代码。作出这样的变化是出于安全性的考虑的。链接:http://www.php.net/downloads.php

  二、 安全使用PHP

  1、安装安全模块

  PHP 的安全模式是为了试图解决共享服务器(shared-server)安全问题而设立的。在结构上,试图在 PHP 层上解决这个问题是不合理的,但修改 WEB 服务器层和操作系统层显得非常不现实。因此许多人,特别是 ISP,目前使用安全模式。

表-1.安全模式配置指令

名称 默认值 类型
safe_mode "0" 布尔型
safe_mode_gid "0" 布尔型
safe_mode_include_dir NULL 字符串
safe_mode_exec_dir "" 字符串
safe_mode_allowed_env_vars PHP_ 字符串
safe_mode_protected_env_vars LD_LIBRARY_PATH 字符串
disable_functions "" 字符串
disable_classes "" 字符串
open_basedir NULL 字符串


以下是该配置选项的简要解释。

(1)safe_mode boolean

是否启用 PHP 的安全模式。

(2)safe_mode_gid

默认情况下,安全模式在打开文件时会做 UID 比较检查。如果你想将其放宽到 GID 比较,则打开 safe_mode_gid。是否在文件访问时使用 UID(FALSE)或者 GID(TRUE)来做检查。

(3)safe_mode_include_dir

当从此目录及其子目录(目录必须在 include_path 中或者用完整路径来包含)包含文件时越过 UID/GID 检查。

从 PHP 4.2.0 开始,本指令可以接受和 include_path 指令类似的风格用分号隔开的路径,而不只是一个目录。

(4)safe_mode_exec_dir

如果 PHP 使用了安全模式,system() 和其它执行系统程序的函数将拒绝启动不在此目录中的程序。

(5)safe_mode_allowed_env_vars

设置某些环境变量可能是潜在的安全缺口。本指令包含有一个逗号分隔的前缀列表。在安全模式下,用户只能改变那些名字具有在这里提供的前缀的环境变量。默认情况下,用户只能设置以 PHP_ 开头的环境变量(例如 PHP_FOO = BAR)。

(6)safe_mode_protected_env_vars

本指令包含有一个逗号分隔的环境变量的列表,最终用户不能用 putenv() 来改变这些环境变量。甚至在 safe_mode_allowed_env_vars 中设置了允许修改时也不能改变这些变量。

(7)disable_functions

本指令允许你基于安全原因禁止某些函数。接受逗号分隔的函数名列表作为参数。 disable_functions 不受安全模式的影响。 本指令只能设置在 php.ini 中。例如你不能将其设置在 httpd.conf。

(8)disable_classes

本指令可以使你出于安全的理由禁用某些类。用逗号分隔类名。disable_classes 不受安全模式的影响。 本指令只能设置在 php.ini 中。例如你不能将其设置在 httpd.conf。该指令自 PHP 4.3.2 起可用。

(9)open_basedir

将 PHP 所能打开的文件限制在指定的目录树,包括文件本身。本指令不受安全模式打开或者关闭的影响。

  2、以安全模式运行PHP

  以安全模式运行PHP是使PHP脚本安全使用的好方法,特别是在允许用户使用自己开发的PHP脚本时。使用安全模式会使PHP在运行函数时检查是否存在安全问题。include、readfile、fopen、file、unlink、rmdir等等:被包含的文件或者该文件所在目录的所有者必须是正在运行的脚本的所有者; Exec、System、Passthm等:要执行的程序必须位于特定的目录(默认为/usr/local/php/bin)。编译PHP时可以用- -with-exe-dir选项设定这个值。

  Mysql_Connect:这个函数用可选的用户名连接MySQL数据库。在安全模式下,用户名必须是当前被执行的脚本的所有者,或运行httpd的用户名(通常是nobody)。

  HTTP Authentication:包含HTTP验证代码脚本所有者的用户ID(数字型)会自动加到验证域。这样可以防止有人通过抓取密码的程序来欺骗同一个服务器上的HTTP验证脚本。

  3、使用用户识别和验证

  有时需要唯一地确认一个用户。用户通常由请求和响应系统确认。用户名/口令组合就是这种系统的一个很好的例子,比如系统要求给出A1i的口令,响应的是Ali的口令。这样验证是因为只有Ali才知道这个口令。

  (1)服务器端用户验征

  这是用于服务端上对PHP程序要求最小的验证方法。只要让Apache来管理对用户的验证就行了。

<ccid_code></ccid_code>AuthName  

"Secret page"  

AuthType     

Basic# The password file has been 

placed outside the web treeAuthUserFile

/home/car2002/website.pw<limit get post>require

valid-user</limit>

  你需要把上述文件(文件名为.htaccess)放在需要保护的地方。用Apache的htpasswd程序,可以建立包含用户名和口令组合的文件。把这个文件放在Web目录树之外,只让该文件的拥有者查看和修改这个文件。当然,Web服务器必须能够读取这个文件。

  如果想读取被保护的目录,Web服务器要求浏览器提供用户名和密码。浏览器弹出对话框,用户可以输入他们的用户名和密码。如果用户名和密码与口令文件中相符合,就允许用户读取被保护的页面;反之,将得到错误页面,告诉用户没有通过验证。被保护的域会显示出来以便用户知道输入那个用户名和密码。

  (2)在PHP中进行用户识别和验证

  和在Apache服务器端进行用户识别和验证相比,在PHP进行用户识别和验证有以下优点:

A、 可注销。用户可以注销身份验证,这在Apache无法实现。

B、 可失效。你可以在一定设计后让登陆失效。如用户登录后60分钟没有浏览你的网站,你可强制他们重新通过验证。

C、 可定制。例如可以用小的JavaApplet加密要传送的口令,而在服务器上用mcryet库解密,这个工作可以在任何支持Java的浏览器上进行。

D、 可基于数据库。你可以用保存在各种各样的数据库里的数据来验证用户,并且记录访问者访问网站的详细日志。

E、 可用于每个页面。你可在每个页面上决定是否需要验证,当然在Apache服务器通过改变域也可以做到这一点。

F、 你也可以使浏览器弹出对话框。下面的例子显示了怎样从,MySQL数据库中检索用名和口令:让用户填人用户名和口令。

<ccid_code></ccid_code><?if (!isset($PHP_AUTH_USER))

{

Header("WWW-authenticate: 

basic realm=\"restricted area\"");

Header( "HTTP/1.0 401 Unauthorized");

echo "You failed to provide 

the correct password...\n";exit;

}

else

{

mysql_select_db("users") ;

$user_id = strtolower($PHP_AUTH_USER);

$result = mysql_query("SELECT password

FROM users " 

."WHERE username = '$username'") ;

$row = mysql_fetch_array($result) ;

if ($PHP_AUTH_PW != $row["password"])

{

Header( "WWW-authenticate:

basic realm=\"restricted area\"Header

(

"HTTP/1.0 401 Unauthorized");

echo "You failed to provide 

the correct password...\n" ;

exit;

} 

}?>Only users with a working username

/password combination can see this

例子:用 PHP 进行 HTTP 认证
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.