PHP是广泛使用的开源服务端脚本语言。通过HTTP或HTTPS协议,Apache Web服务允许用户访问文件或内容。服务端脚本语言的错误配置会导致各种问题。因此,PHP应该小心使用。以下是为系统管理员准备的,安全配置PHP的25个实践事例。 用于下文的PHP设置样例 - DocumentRoot:/var/www/html
- 默认Web服务:Apache(可以使用Lighttpd或Nginx代替)
- 默认PHP配置文件:/etc/php.ini
- 默认PHP Extensions配置目录:/etc/php.d/
- PHP安全配置样例文件:/etc/php.d/security.ini(需要使用文本编辑器创建这个文件)
- 操作系统:RHEL / CentOS / Fedora Linux(指令应该可以在所有其他Linux发行版,如Debian / Ubuntu,或是Unix-like的操作系统,如OpenBSD / FreeBSD / HP-UX下正常运行)
- PHP服务的默认TCP/UDP端口:none
下午列出的大部分操作,都是基于 root 用户能在 bash 或其他现代 shell 上执行操作的假设。 样例输出 1 2 3 | PHP 5.3.3 (cli) (built: Oct 24 2011 08:35:41)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2010 Zend Technologies
|
本文使用的操作系统 1 | $ cat /etc/redhat-release
|
样例输出 1 | Red Hat Enterprise Linux Server release 6.1 (Santiago)
|
#1:知彼 基于PHP的应用面临着各种各样的攻击: - XSS:对PHP的Web应用而言,跨站脚本是一个易受攻击的点。攻击者可以利用它盗取用户信息。你可以配置Apache,或是写更安全的PHP代码(验证所有用户输入)来防范XSS攻击
- SQL注入:这是PHP应用中,数据库层的易受攻击点。防范方式同上。常用的方法是,使用mysql_real_escape_string()对参数进行转义,而后进行SQL查询。
- 文件上传:它可以让访问者在服务器上放置(即上传)文件。这会造成例如,删除服务器文件、数据库,获取用户信息等一系列问题。你可以使用PHP来禁止文件上传,或编写更安全的代码(如检验用户输入,只允许上传png、gif这些图片格式)
- 包含本地与远程文件:攻击者可以使远程服务器打开文件,运行任何PHP代码,然后上传或删除文件,安装后门。可以通过取消远程文件执行的设置来防范
- eval():这个函数可以使一段字符串如同PHP代码一样执行。它通常被攻击者用于在服务器上隐藏代码和工具。通过配置PHP,取消eval()函数调用来实现
- Sea-surt Attack(Cross-site request forgery,CSRF。跨站请求伪造):这种攻击会使终端用户在当前账号下执行非指定行为。这会危害终端用户的数据与操作安全。如果目标终端用户的账号用于管理员权限,整个Web应用都会收到威胁。
#2:减少内建的PHP模块 执行下面指令可以查看当前PHP所编译的模块 样例输出: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | [PHP Modules]
apc
bcmath
bz2
calendar
Core
ctype
curl
date
dom
ereg
exif
fileinfo
filter
ftp
gd
gettext
gmp
hash
iconv
imap
json
libxml
mbstring
memcache
mysql
mysqli
openssl
pcntl
pcre
PDO
pdo_mysql
pdo_sqlite
Phar
readline
Reflection
session
shmop
SimpleXML
sockets
SPL
sqlite3
standard
suhosin
tokenizer
wddx
xml
xmlreader
xmlrpc
xmlwriter
xsl
zip
zlib
[Zend Modules]
Suhosin
|
从性能与安全性的角度考虑,我建议使用PHP时减少不必要的模块。例如上面的sqlite3是不必要的。那么可以通过删除或重命名/etc/php.d/sqlite3.ini文件来取消它: 或 有些模块则只能通过使用重新编译安装PHP来移除。例如,从php.net下载PHP源码后,使用下面指令编译GD,fastcgi和MySQL支持: 1 | . /configure --with-libdir=lib64 --with-gd --with-mysql --prefix= /usr -- exec -prefix= /usr --bindir= /usr/bin --sbindir= /usr/sbin --sysconfdir= /etc --datadir= /usr/share --includedir= /usr/include --libexecdir= /usr/libexec --localstatedir= /var --sharedstatedir= /usr/com --mandir= /usr/share/man --infodir= /usr/share/info --cache- file =.. /config .cache --with-config- file -path= /etc --with-config- file -scan- dir = /etc/php .d -- enable -fastcgi -- enable -force-cgi-redirect
|
更多信息请查看:how to compile and reinstall php on Unix like operating system #3:防止PHP信息泄漏 可以通过取消export_php,对PHP信息泄漏进行限制。编辑/etc/php.d/security.ini如下: expose_php会在HTTP Header中添加服务器上,包括版本在内的PHP信息(例如X-Powered-By: PHP/5.3.3)。同时,PHP的全局统一标识符也会暴露。如果export_php启用的话,可以通过下面命令查看PHP版本信息: 1 | $ curl -I http: //www .cyberciti.biz /index .php
|
样例输出: 1 2 3 4 5 6 7 | HTTP /1 .1 200 OK
X-Powered-By: PHP /5 .3.3
Content- type : text /html ; charset=UTF-8
Vary: Accept-Encoding, Cookie
X-Vary-Options: Accept-Encoding;list-contains= gzip ,Cookie;string-contains=wikiToken;string-contains=wikiLoggedOut;string-contains=wiki_session
Last-Modified: Thu, 03 Nov 2011 22:32:55 GMT
...
|
建议同时隐藏Apache版本等信息:ServerTokens and ServerSignature directives in httpd.conf to hide Apache version #4:最小化可载入的PHP模块(动态Extension) PHP支持“Dynamic Extensions”。默认情况下,RHEL会载入/etc/php.d/目录下的所有Extension模块。如需启用或取消某一模块,只需把/etc/php.d/目录下配置文件把该模块注释掉。也可以把文件删除或重命名该模块的配置文件。为了最优化PHP的性能和安全性,应只启用Web应用所需的Extension。例如,用下面命令取消GD模块: 启用则是: #5:记录所有PHP错误 不要把PHP错误信息输出给所用用户。编辑/etc/php.d/security.ini,如下修改: 确保把所有错误信息记录到日志文件 1 2 | log_errors=On
error_log= /var/log/httpd/php_scripts_error .log
|
#6:禁止文件上传 为安全考虑,如下编辑/etc/php.d/security.ini取消文件上传 如用户的确需要上传文件,那么把它启用,而后限制PHP接受的最大文件大小: 1 2 3 | file_uploads=On
upload_max_filesize=1M
|
#7:关闭远程代码执行 如果这个特性被启动,PHP可以通过allow_url_fopen,在file_get_contents()、include、require中获取诸如FTP或网页内容这些远程数据。程序员经常忘记了对用户输入进行过滤,而如果这些函数调用了这些数据,则形成了注入漏洞。在基于PHP的Web应用中,大量代码中的注入漏洞都由此产生。可以通过编辑/etc/php.d/security.ini来关闭该特性: 除此之外,建议把allow_url_include也取消掉:
|