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 上执行操做的假设。 $ php -v 样例输出 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 本文使用的操做系统 $ cat /etc/redhat-release 样例输出 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所编译的模块 $ php -m 样例输出: [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文件来取消它: # rm /etc/php.d/sqlite3.ini 或 # mv /etc/php.d/sqlite3.ini /etc/php.d/sqlite3.disable 有些模块则只能经过使用从新编译安装PHP来移除。例如,从php.net下载PHP源码后,使用下面指令编译GD,fastcgi和MySQL支持: ./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=Off expose_php会在HTTP Header中添加服务器上,包括版本在内的PHP信息(例如X-Powered-By: PHP/5.3.3)。同时,PHP的全局统一标识符也会暴露。若是export_php启用的话,能够经过下面命令查看PHP版本信息: $ curl -I http://www.cyberciti.biz/index.php 样例输出: 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模块: # cd /etc/php.d/ # mv gd.{ini,disable} # <span style="text-decoration: underline;">/sbin/service httpd restart</span> 启用则是: # mv gd.{disable,ini} # <span style="text-decoration: underline;">/sbin/service httpd restart</span> #5:记录全部PHP错误 不要把PHP错误信息输出给所用用户。编辑/etc/php.d/security.ini,以下修改: display_errors=Off 确保把全部错误信息记录到日志文件 log_errors=On error_log=/var/log/httpd/php_scripts_error.log #6:禁止文件上传 为安全考虑,以下编辑/etc/php.d/security.ini取消文件上传 file_uploads=Off 如用户的确须要上传文件,那么把它启用,然后限制PHP接受的最大文件大小: file_uploads=On # user can only upload upto 1MB via php upload_max_filesize=1M #7:关闭远程代码执行 若是这个特性被启动,PHP能够经过allow_url_fopen,在file_get_contents()、include、require 中获取诸如FTP或网页内容这些远程数据。程序员常常忘记了对用户输入进行过滤,而若是这些函数调用了这些数据,则造成了注入漏洞。在基于PHP的Web 应用中,大量代码中的注入漏洞都由此产生。能够经过编辑/etc/php.d/security.ini来关闭该特性: allow_url_fopen=Off 除此以外,建议把allow_url_include也取消掉: allow_url_include=Off #8:启用SQL安全模式 以下修改/etc/php.d/security.ini: sql.safe_mode=On 当此特性被启用,mysql_connect()和mysql_pconnect()会忽略传入的全部参数。与此同时,你须要在代码上作些相应的修改。第三方以及开源应用,如Wordpress,在sql.safe_mode下可能没法正常工做。同时建议关闭5.3.x版本的PHP的 magic_quotes_gpc过滤,由于它简单粗暴又没效率。使用mysql_escape_string()以及自定义的过滤函数会更好一些 magic_quotes_gpc=Off #9:控制POST的数据大小 HTTP POST一般做为请求的一部分,被客户端用于向Apache Web服务器发送数据,如上传文件或提交表单。***者会尝试发送超大的POST请求去消耗服务器的资源。以下编辑/etc/php.d/security.ini限制POST的最大大小: ; 在这里设置一个靠谱的数值 post_max_size=1K 这里设置了1K的最大大小。这个设置会影响到文件上传。要上传大文件,这个值须要比update_max_filesize大。 建议在Apache中限制可用的请求方法,编辑httpd.conf以下: <Directory /var/www/html> <LimitExcept GET POST> Order allow,deny </LimitExcept> ## Add rest of the config goes here... ## </Directory> #10:资源控制(DoS控制) 设置每一个PHP脚本的最大运行时间。另外建议限制用于处理请求数据的最大时间,以及最大可用内存数。 # 单位:秒 max_execution_time = 30 max_input_time = 30 memory_limit = 40M #11:为PHP安装Suhosin高级保护系统 具体参考Suhosin项目页:project page #12:取消危险的PHP函数 PHP有大量可用于***服务器的函数,如使用不当则会成为漏洞。以下取消这些函数: disable_functions =exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source #13:PHP Fastcgi / CGI – cgi.force_redirect管理 PHP可与Fastcgi协同工做。Fastcgi能够减小Web服务器的内存足迹(memory footprint),并改善PHP性能。能够参考这个来配置Apache2+PHP+FastCGI。在这个配置中,cgi.force_redirect会阻止用户经过访问URL来调用PHP。为安全考虑,启用该特性: ; Enable cgi.force_redirect for security reasons in a typical *Apache+PHP-CGI/FastCGI* setup cgi.force_redirect=On #14:PHP用户与用户组ID mod_fastcgi是Apache Web服务的一个cgi模块,可链接到外部的FASTCGI服务器。你须要确保PHP使用非root用户运行。若其使用root或是UID小于100的用户权限,它就能够访问,乃至操做系统文件。经过Apache’s suEXEC或mod_suPHP,可在非特权用户下执行PHP CGI。suEXEC能够是Apache调用CGI程序的user ID不一样于运行Apache的user ID。以下: # ps aux | grep php-cgi 样例输出: phpcgi 6012 0.0 0.4 225036 60140 S Nov22 0:12 /usr/bin/php-cgi phpcgi 6054 0.0 0.5 229928 62820 S Nov22 0:11 /usr/bin/php-cgi phpcgi 6055 0.1 0.4 224944 53260 S Nov22 0:18 /usr/bin/php-cgi phpcgi 6085 0.0 0.4 224680 56948 S Nov22 0:11 /usr/bin/php-cgi phpcgi 6103 0.0 0.4 224564 57956 S Nov22 0:11 /usr/bin/php-cgi phpcgi 6815 0.4 0.5 228556 61220 S 00:52 0:19 /usr/bin/php-cgi phpcgi 6821 0.3 0.5 228008 61252 S 00:55 0:12 /usr/bin/php-cgi 能够经过spawn-fcgi来生成phpcgi用户的远程或本地FastCGI进程(前提是有这个用户): # spawn-fcgi -a 127.0.0.1 -p 9000 -u phpcgi -g phpcgi -f /usr/bin/php-cgi 如今能够配置Apache、Lighthttpd或Nginx Web服务调用运行在127.0.0.1:9000的FastCGI。 #15:限制PHP访问文件系统 open_basedir会限制PHP的运行目录,例如经过fopen()之类的函数可访问的目录。若是访问的目录不在open_basedir以内,PHP会拒绝该访问。不要使用软连接做为工做区。例如,只容许访问/var/www/html而非/var/www、/tmp或/etc目录: ; Limits the PHP process from accessing files outside ; of specifically designated directories such as /var/www/html/ open_basedir="/var/www/html/" ; ------------------------------------ ; Multiple dirs example ; open_basedir="/home/httpd/vhost/cyberciti.biz/html/:/home/httpd/vhost/nixcraft.com/html/:/home/httpd/vhost/theos.in/html/" ; ------------------------------------ #16:Session路径 PHP Session用户提供数据保存功能,以便后续访问。这可使应用可定制性更强,提高吸引力。全部Session相关的数据会被保存在session.save_path中。RHEL/CentOS/Fedora Linux的默认设置以下: session.save_path="/var/lib/php/session" ; Set the temporary directory used for storing files when doing file upload upload_tmp_dir="/var/lib/php/session" 确认这个路径在/var/www/html以外,且不可被其余系统用户访问: # ls -Z /var/lib/php/ 样例输出: drwxrwx---. root apache system_u ![]() |