2. 安全模式
在多用户环境中部署PHP时(如ISP的共享服务器上),可能要限制PHP的功能。可以想见,如果为所有用户提供PHP的所有功能,会暴露服务器的漏洞,还可能会破坏服务器的资源和文件。在共享服务器上使用PHP时,作为防护,PHP可以采用一种受限模式或安全模式运行。
启用安全模式有很多影响,包括自动禁用很多功能和可能不安全的各种特性,如果这些功能和特性在本地脚本中被误用,很有可能造成破坏。禁用的函数和特性包括parse_ini_file()、chmod()、chown()、chgrp()、exec()、system()和反引号操作符。启用安全模式还能确保所执行脚本的所有者与脚本访问的文件或目录的所有者相一致。
此外,启用安全模式还可以通过其他PHP配置指令激活另外一些限制,这一节将分别介绍这些指令。
l safe_mode (On, Off)
作用域:PHP_INI_SYSTEM;默认值:Off。
启用这个安全模式指令将使PHP在上述约束条件下运行。
l safe_mode_gid (On, Off)
作用域:PHP_INI_SYSTEM;默认值:Off。
启用安全模式时,如果还启用了safe_mode_gid,在打开文件时就会强制完成GID(组ID)检查。禁用safe_mode_gid时,会强制完成一个更为严格的UID(用户ID)检查。
l safe_mode_include_dir (string)
作用域:PHP_INI_SYSTEM;默认值:Null。
启用safe_mode和safe_mode_gid时,safe_mode_include_dir为避免UID/GID检查提供了一个安全的避风港。当打开的文件位于指定的目录中时,将忽略UID/GID检查。
l safe_mode_exec_dir (string)
作用域:PHP_INI_SYSTEM;默认值:Null。
启用安全模式时,safe_mode_exec_dir参数会限制通过exec()函数只能执行指定目录中的可执行程序。例如,如果希望限制为只能执行/usr/local/bin下的函数,可以使用指令:
![]()
l safe_mode_allowed_env_vars (string)
作用域:PHP_INI_SYSTEM;默认值:PHP_。
启用安全模式时,可以使用safe_mode_allowed_env_vars指令限制用户能通过PHP脚本修改哪些操作系统级环境变量。例如,如下设置safe_mode_allowed_env_vars指令,则只允许修改以PHP_或MYSQL_开头的变量:
![]()
要记住,这个指令的值为空表示用户可以修改任何环境变量。
l safe_mode_protected_env_vars (string)
作用域:PHP_INI_SYSTEM;默认值:LD_LIBRARY_PATH。
利用safe_mode_protected_env_vars指令,可以明确地防止修改某些环境变量。例如,如果希望防止用户修改PATH和LD_LIBRARY_PATH变量,可以使用以下指令:
![]()
l open_basedir (string)
作用域:PHP_INI_SYSTEM;默认值:Null。
与Apache的DocumentRoot相似,PHP的open_basedir指令可以建立一个基目录,所有文件操作都限制在此目录中。这会防止用户进入到服务器的其他受限区中。例如,假设所有Web素材都位于目录/home/www中。为防止用户通过一些简单的PHP命令查看以及可能操作诸如etc/passwd等文件,可以考虑将open_basedir设置为:
![]()
注意,这个指令的影响并不依赖于safe_mode指令。
l disable_functions (string)
作用域:PHP_INI_SYSTEM;默认值:Null。
在某些环境下,你可能希望完全禁用某些默认函数,如exec()和system()。将这些函数赋给disable_functions参数就能实现禁用,如下:
![]()
注意,这个指令的影响并不依赖于safe_mode指令。
l disable_classes (string)
作用域:PHP_INI_SYSTEM;默认值:Null。
PHP采纳了面向对象范型,根据由此提供的新功能,可以想见,用不了多久就会有非常多的类库。但是,你可能不希望启用这些类库中的某些类。通过disable_classes指令可以防止使用这些类。例如,如果希望禁用两个特定的类:administrator和janitor,可以使用如下指令:
![]()
注意,这个指令的影响并不依赖于safe_mode指令。
l ignore_user_abort (Off, On)
作用域:PHP_INI_ALL;默认值:On。
在浏览器某个页面时,也许页面完全加载之前你就退出或关闭了浏览器,这种情况是不是屡屡发生呢?通常这样做并无害处。但是,如果服务器正在更新重要的用户信息,或者正在完成一个商业交易,会怎么样呢?启用ignore_user_abort会让服务器忽略由于用户或浏览器引起的中断所造成的会话中止。
3. 语法突出显示
PHP可以突出显示源代码。通过将PHP脚本的扩展名赋为.phps(这是默认的扩展名,下面将了解到,这是可以修改的),或者利用show_source()或highlight_file()函数,就可以启用此功能。要使用.phps扩展名,需要向httpd.conf中增加以下代码:
![]()
对于突出显示的源代码,通过以下6个指令,可以控制其中字符串、注释、关键字、背景、默认文本和HTML部分的颜色。例如,通常称为“黑色”的颜色可以分别表示为rgb(0,0,0)、#000000或black。
l highlight.string (string)
作用域:PHP_INI_ALL;默认值:#DD0000。
l highlight.comment (string)
作用域:PHP_INI_ALL;默认值:#FF9900。
l highlight.keyword (string)
作用域:PHP_INI_ALL;默认值:#007700。
l highlight.bg (string)
作用域:PHP_INI_ALL;默认值:#FFFFFF。
l highlight.default (string)
作用域:PHP_INI_ALL;默认值:#0000BB。
l highlight.html (string)
作用域:PHP_INI_ALL;默认值:#000000。
4. 杂项
杂项这一类中只包含一个指令:expose_php。
l expose_php (On, Off)
作用域:PHP_INI_SYSTEM;默认值:On。
如果攻击者能够得到任何一条关于Web服务器的信息,都会增加他成功破坏服务器的机会。一个简单的办法是通过服务器签名获得有关服务器特点的关键信息。例如,在默认情况下,Apache会在每个响应首部中广播如下信息:
![]()
通过禁用expose_php,能防止Web服务器签名(如果启用)广播上述事实(即已经安装了PHP)。虽然还需要更多的措施来确保充分的服务器保护,但不管怎样,强烈建议保护这些服务器属性。
注解 可以在httpd.conf文件中将ServerSignature设置为Off,这会禁止Apache广播其服务器签名。
5. 资源限制
虽然PHP 5在资源处理功能方面有长足的进步,但还是要当心,应确保PHP脚本不会由于程序员或用户的动作而独占服务器资源。受这种过度耗费资源影响的三个方面是脚本执行时间、脚本输入处理时间和内存。这些方面可以通过以下3个指令来控制。
l max_execution_time (integer)
作用域:PHP_INI_ALL;默认值:30。
max_execution_time参数对PHP脚本可以执行的时间设置了一个上限,以秒为单位。如果将这个参数设置为0,将取消所有最大限制。注意,通过PHP命令(如exec()和system())执行的外部程序所花费的时间不算在此限制之内。
l max_input_time (integer)
作用域:PHP_INI_ALL;默认值:60。
max_input_time参数对PHP脚本解析请求数据所用的时间设置了一个限制,以秒为单位。使用PHP的文件上传特性上传大文件时,这个参数尤其有用。文件上传将在第15章讨论。
l memory_limit (integer)M
作用域:PHP_INI_ALL;默认值:8M。
memory_limit参数确定PHP脚本可以分配的最大内存量,以MB为单位。
6. 错误处理和日志
PHP为报告和记录PHP在编译时和运行时生成的错误、警告和提示(以及某些用户动作所导致的错误)提供了一种方便灵活的方法。开发人员可以控制报告的敏感度,这些信息是否显示在浏览器中及如何显示,信息将记录在文件中还是系统日志中(在UNIX下是syslog,在Windows下是事件日志)。下面15个指令将控制错误处理行为。
l error_reporting (string)
作用域:PHP_INI_ALL;默认值:Null。
error_reporting指令确定PHP错误报告敏感度的级别。有13个预定的错误级别,每一个都唯一对应于应用程序或服务器的功能。这些级别列在表2-1中。
可以把error_reporting设置为任何单个级别,或者使用布尔操作符组合这些级别。例如,假设只想报告错误,可以使用如下设置:
![]()
如果要跟踪所有错误,但不报告用户生成的警告和提示,可以使用如下设置:
![]()
在应用程序开发和初始布署阶段,应当将敏感度设置为最高级别,或E_ALL。但是,一旦解决了所有主要bug之后,就要考虑降低敏感度。
表2-1 PHP的错误报告级别
|
名 |
描 述 |
|
E_ALL |
报告所有错误和警告 |
|
E_ERROR |
报告致命的运行时错误 |
|
E_WARNING |
报告非致命的运行时错误 |
|
E_PARSE |
报告编译时解析错误 |
|
E_NOTICE |
报告运行时注意消息,如未初始化变量 |
|
E_STRICT |
PHP版本可移植性建议 |
|
E_CORE_ERROR |
报告在PHP启动时发生的致命错误 |
|
E_CORE_WARNING |
报告在PHP启动时发生的非致命错误 |
|
E_COMPILE_ERROR |
报告致命的编译时错误 |
|
E_COMPILE_WARNING |
报告非致命的编译时错误 |
|
E_USER_ERROR |
报告用户引发的致命错误消息 |
|
E_USER_WARNING |
报告用户引发的非致命错误消息 |
|
E_USER_NOTICE |
报告用户引发的注意消息 |
l display_errors (On, Off)
作用域:PHP_INI_ALL;默认值:On。
启用display_errors时,将输出error_reporting指定级别之上的所有错误。在开发阶段要考虑启用这个参数。当部署应用程序时,所有错误都应当记录为日志,这可以通过启用log_errors并使用error_log指定日志目标来实现。
l display_startup_errors (On, Off)
作用域:PHP_INI_ALL;默认值:Off。
禁用display_startup_errors时,可防止将PHP启动过程中的错误显示给用户。
l log_errors (On, Off)
作用域:PHP_INI_ALL;默认值:Off。
错误消息对于确定PHP应用程序执行期间可能产生的问题很有意义。启用log_errors时,则告诉PHP应当记录这些错误,可以记录在某个文件中,或者记录到syslog中。具体的目标由另一个参数error_log来确定。
l log_errors_max_len (integer)
作用域:PHP_INI_ALL;默认值:1024。
这个参数确定一条日志消息的最大长度,以字节为单位。将此参数设置为0则不限制最大长度。
l ignore_repeated_errors (On, Off)
作用域:PHP_INI_ALL;默认值:Off。
如果你经常查看日志,应该知道,有些错误发生在同一文件的同一行,实在没有必要重复记录。禁用此参数就可以防止记录这些重复的错误。
l ignore_repeated_source (On, Off)
作用域:PHP_INI_ALL;默认值:Off。
这相当于ignore_repeated_errors参数的一个变种,如果禁用ignore_repeated_source,在忽略重复错误时将不考虑错误来源。这表示每个错误消息最多只记录一次。
l report_memleaks (On, Off)
作用域:PHP_INI_ALL;默认值:Off。
这个参数只在PHP以调试模式编译时才有效,它将确定是否显示或记录内存泄漏。除了要处于调试模式,错误级别还必须至少是E_WARNING。
l track_errors (On, Off)
作用域:PHP_INI_ALL;默认值:Off。
启用track_errors会让PHP在$php_error_msg变量中存储最近的错误消息。这个变量的作用域仅限于出现错误的特定脚本内。
l html_errors (On, Off)
作用域:PHP_INI_SYSTEM;默认值:On。
默认情况下,PHP把错误消息包围在HTML标记内。有时,你可能不希望PHP这样做,所以可以通过html_errors参数来禁用这种行为。
l docref_root (string)
作用域:PHP_INI_ALL;默认值:Null。
如果启用html_errors,PHP就会包括一个指向错误详细描述(位于官方手册)的链接,这就会指向官方手册。不过,最好不要链接到官方网站,而应指向手册的本地副本。本地手册的位置由docref_root指定的路径来确定。
l docref_ext (string)
作用域:PHP_INI_ALL;默认值:Null。
用于提供关于错误的额外信息时,docref_ext参数会告诉PHP本地手册页面的扩展名(参见docref_root)。
l error_prepend_string (string)
作用域:PHP_INI_ALL;默认值:Null。
如果希望在输出错误之前向用户传递附加的信息,就可以利用error_prepend_string参数,在自动生成的错误输出前面加上一个字符串(包含格式化标记)。
l error_append_string (string)
作用域:PHP_INI_ALL;默认值:Null。
如果希望在输出错误之后向用户传递附加的信息,就可以利用error_append_string参数,在自动生成的错误输出后面加上一个字符串(包含格式化标记)。
l error_log (string)
作用域:PHP_INI_ALL;默认值:Null。
如果启用log_errors,error_log指令将指定消息目标。PHP支持将错误记录到指定文件和操作系统日志中。在Windows下,将error_log设置为syslog会把消息记录到事件日志中。







