ホームページ  >  記事  >  バックエンド開発  >  25 システム管理者のための PHP 保険の実践

25 システム管理者のための PHP 保険の実践

WBOY
WBOYオリジナル
2016-06-13 12:11:021444ブラウズ

25 システム管理者のための PHP セキュリティ対策

PHP は、広く使用されているオープン ソースのサーバー側スクリプト言語です。 Apache Web サービスを使用すると、ユーザーは HTTP または HTTPS プロトコルを通じてファイルやコンテンツにアクセスできます。サーバーサイドのスクリプト言語の構成が間違っていると、さまざまな問題が発生する可能性があります。したがって、PHP は注意して使用する必要があります。ここでは、システム管理者向けに PHP を安全に構成する方法に関する 25 の実践的な例を示します。

以下で使用されるサンプル PHP 設定

  • DocumentRoot: /var/www/html
  • デフォルト Web サービス: Apache (代わりに Lighttpd または Nginx を使用してください)
  • デフォルトの PHP 設定ファイル: /etc/php.ini
  • デフォルトの PHP 拡張機能設定ディレクトリ: /etc/php.d/
  • PHP セキュリティ設定サンプル ファイル: /etc/php.d/security.ini (このファイルを作成するにはテキスト エディターを使用する必要があります)
  • オペレーティング システム: RHEL / CentOS / Fedora Linux (この手順は他のすべての環境でも機能するはずです) Debian / Ubuntu などの Linux ディストリビューション、または OpenBSD / FreeBSD / HP-UX などの Unix 系オペレーティング システムで通常動作します)
  • PHP サービスのデフォルト TCP/UDP ポート: なし

今日の午後にリストされた操作のほとんどは、root ユーザーが bash またはその他の最新のシェルで操作を実行できるという前提に基づいています。

$ 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 アプリケーションの場合、クロスサイト スクリプティングは脆弱な点です。攻撃者はこれを使用してユーザー情報を盗むことができます。 XSS 攻撃を防ぐために、Apache を構成するか、より安全な PHP コード (すべてのユーザー入力を検証する) を作成できます。
  • SQL インジェクション: これは、PHP アプリケーションのデータベース層における攻撃の脆弱点です。予防方法は上記と同様です。一般的な方法は、mysql_real_escape_string() を使用してパラメータをエスケープし、SQL クエリを実行することです。
  • ファイルのアップロード: 訪問者がファイルをサーバーに配置 (アップロード) できるようにします。これにより、サーバーファイルやデータベースの削除、ユーザー情報の取得など、一連の問題が発生します。 PHP を使用してファイルのアップロードを無効にしたり、より安全なコードを記述したりできます (ユーザー入力を検証し、png や gif などの画像形式のアップロードのみを許可するなど)
  • ローカル ファイルとリモート ファイルが含まれます。攻撃者は、リモートサーバーはファイルを開き、PHP コードを実行し、ファイルをアップロードまたは削除し、バックドアをインストールします。リモートファイル実行の設定を解除することで回避できます。
  • eval(): この関数は、PHP コードのように文字列を実行させることができます。これは、攻撃者がサーバー上のコードやツールを隠すためによく使用されます。 PHP を構成し、eval() 関数呼び出しをキャンセルすることで、
  • Sea-surt 攻撃 (クロスサイト リクエスト フォージェリ、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

一部のモジュールは、Install 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

詳細については、「php をコンパイルして再インストールする方法」を参照してください。 Unix 系オペレーティングシステム

#3: PHP 情報漏洩を防ぐ

export_php をキャンセルすることで PHP 情報漏洩を制限できます。 /etc/php.d/security.ini を次のように編集します。

expose_php=Off

Expose_php は、バージョンを含むサーバー上の PHP 情報を HTTP ヘッダーに追加します (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 バージョンとその他の情報は、同時に: Apache のバージョンを隠すための httpd .conf の ServerTokens と ServerSignature ディレクティブ

#4: ロード可能な PHP モジュールを最小限にする (動的拡張)

PHP は「動的拡張」をサポートします。デフォルトでは、RHEL はすべての拡張モジュールを /etc/php.d/ ディレクトリにロードします。モジュールを有効またはキャンセルする必要がある場合は、/etc/php.d/ ディレクトリの設定ファイル内のモジュールをコメントアウトするだけです。ファイルを削除したり、モジュールの構成ファイルの名前を変更したりすることもできます。 PHP のパフォーマンスとセキュリティを最適化するには、Web アプリケーションに必要な拡張機能のみを有効にする必要があります。たとえば、次のコマンドを使用して 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=Onerror_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 phpupload_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 = 30max_input_time = 30memory_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:object_r:httpd_var_run_t:s0 session

  注:ls -Z会显示SELinux的安全信息,如文件模式,user,group,安全信息,文件名等。

  #17:保证PHP,软件及操作系统更新到最新

  维护Linux、Apache、PHP和MySQL服务器的一项重要工作是更新安全补丁。所有的PHP安全更新应尽快进行审查并更新。可使用如下命令(如果通过包管理器来安装PHP):

# yum update

  或

# apt-get update && apt-get upgrade

  可以配置Red Hat / CentOS / Fedora Linux通过Email发送yum的包更新提醒,或是Debian / Ubuntu Linux下的apticron发送提醒。又或通过cron计划任务进行更新。

  注:查看php.net以获取最新的PHP版本信息

  #18:限制文件及目录访问

  确认以Apache或www这种非root用户运行Apache。/var/www/html目录下的owner也应是非root用户:

# chown -R apache:apache /var/www/html/

  DocumentRoot下的文件应禁止运行或创建。设置该目录下的文件权限为0444(只读):

# chmod -R 0444 /var/www/html/

  设置该目录下的所有文件夹权限为0445

# find /var/www/html/ -type d -print0 | xargs -0 -I {} chmod 0445 {}

  #19:Apache、PHP、MySQL配置文件的写入保护

  使用chattr命令给这些配置文件加上写入保护:

# chattr +i /etc/php.ini# chattr +i /etc/php.d/*# chattr +i /etc/my.ini# chattr +i /etc/httpd/conf/httpd.conf# chattr +i /etc/

  同样可以为/var/www/html目录加上写入保护

# chattr +i /var/www/html/file1.php# chattr +i /var/www/html/

  #20:使用Linux安全拓展(如SELinux)

  Linux有各种安全方案来防止服务程序的错误配置或漏洞。尽可能使用SELinux或其他Linux安全方案限制网络和程序。例如,SELinux为Linux内核或Apache Web服务提供不同的安全策略。使用下面命令列出所有Apache保护信息:

# getsebool -a | grep httpd

  样例输出:

 allow_httpd_anon_write --> off allow_httpd_mod_auth_ntlm_winbind --> off allow_httpd_mod_auth_pam --> off allow_httpd_sys_script_anon_write --> off httpd_builtin_scripting --> on httpd_can_check_spam --> off httpd_can_network_connect --> off httpd_can_network_connect_cobbler --> off httpd_can_network_connect_db --> off httpd_can_network_memcache --> off httpd_can_network_relay --> off httpd_can_sendmail --> off httpd_dbus_avahi --> on httpd_enable_cgi --> on httpd_enable_ftp_server --> off httpd_enable_homedirs --> off httpd_execmem --> off httpd_read_user_content --> off httpd_setrlimit --> off httpd_ssi_exec --> off httpd_tmp_exec --> off httpd_tty_comm --> on httpd_unified --> on httpd_use_cifs --> off httpd_use_gpg --> off httpd_use_nfs --> off

  取消Apache cgi支持可以输入:

# setsebool -P httpd_enable_cgi off

  详细参考:Red Hat SELinux guide

  #21:安装Mod_security

  ModSecurity是一个开源的入侵检测和防范的Web应用引擎。安装mod_security可以保护Apache和PHP应用免受XSS和其他攻击:

## A few Examples ## # Do not allow to open files in /etc/ SecFilter /etc/ # Stop SQL injection SecFilter "delete[[:space:]]+from" SecFilter "select.+from"

  #22:如有可能,在Chroot Jail下运行Apache / PHP

  在Chroot Jail下运行Apache / PHP可以最小化可能受到的损失,使其局限于文件系统下的一小块。可以使用一般的chroot来配置Apache:chroot kind of setup with Apache。不过我建议使用FreeBSD jails、XEN,KVM或OpenVZ虚拟化。

  #23:使用防火墙限制传出连接

  攻击者会使用wget之类的工具从你的Web服务器下载文件。使用iptables来阻挡Apache用户的传出连接。ipt_owner模块会为本地数据包的生成者分配不同角色。它只对OUTPUT chain有效。下面指令允许vivek用户通过80端口进行外部访问:

/sbin/iptables -A OUTPUT -o eth0 -m owner --uid-owner vivek -p tcp --dport 80 -m state --state NEW,ESTABLISHED  -j ACCEPT

  下面的样例则是阻挡所有Apache用户的传出连接,只允许smtp服务及spam识别API服务通过:

# ....   /sbin/iptables --new-chain apache_user /sbin/iptables --append OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT /sbin/iptables --append OUTPUT -m owner --uid-owner apache -j apache_user # allow apache user to connec to our smtp server  /sbin/iptables --append apache_user -p tcp --syn -d 192.168.1.100 --dport 25 -j RETURN # Allow apache user to connec to api server for spam validation /sbin/iptables --append apache_user -p tcp --syn -d  66.135.58.62 --dport 80 -j RETURN /sbin/iptables --append apache_user -p tcp --syn -d  66.135.58.61 --dport 80 -j RETURN /sbin/iptables --append apache_user -p tcp --syn -d  72.233.69.89 --dport 80 -j RETURN /sbin/iptables --append apache_user -p tcp --syn -d  72.233.69.88 --dport 80 -j RETURN ######################### ## Add more rules here ## ######################### # No editing below # Drop everything for apache outgoing connection /sbin/iptables --append apache_user -j REJECT

  #24:查看并审查日志

  查看Apache日志文件:

 # tail -f /var/log/httpd/error_log # grep 'login.php' /var/log/httpd/error_log # egrep -i "denied|error|warn" /var/log/httpd/error_log

  查看PHP日志文件:

 # tail -f /var/log/httpd/php_scripts_error.log # grep "...etc/passwd" /var/log/httpd/php_scripts_error.log

  查看日志文件可以让你知道服务器正在承受何种攻击,并分析当前安全级别是否足够。启用审查服务用于系统审查,可审查SELinux时间,验证事件,文件修改,账号修改等。建议使用Linux System Monitoring Tools来监控Web服务器。

  #25:把服务分离到不同的服务器或虚拟机

  对于比较庞大的安装配置,建议把运行、数据库、静态与动态内容分离到不同的服务器

/////////////// / ISP/Router / //////////////   \    |    Firewall      \       |      +------------+      | LB01       |      +------------+                 +--------------------------+                   |                 | static.lan.cyberciti.biz |                   +-----------------+--------------------------+                                     | phpcgi1.lan.cyberciti.biz|                                     +--------------------------+                                     | phpcgi2.lan.cyberciti.biz|                                     +--------------------------+                                     | mysql1.lan.cyberciti.biz |                                     +--------------------------+                                     | mcache1.lan.cyberciti.biz|                                     +--------------------------+

  在不同的服务器或虚拟机下运行不同的网络服务,这可以减少被入侵对其他服务的影响。例如,一个攻击者入侵了Apache,那就可以访问同一服务器下的其他服务(如MySQL,email服务等)。但在上述例子中则不会:

  • static.lan.cybercity.biz – 使用lighttpd或nginx存放js/css/images等静态资源
  • phpcgi1.lan.cyberciti.biz和phpcgi2.lan.cyberciti.biz – Apache Web服务+PHP,用于生成动态内容
  • mysql1.lan.cyberciti.biz – MySQL数据库服务
  • mcache1.lan.cyberciti.biz – Memcached服务(MySQL的高速缓存系统)。它使用libevent或epoll来适应任意连接数。而且它使用的是非阻塞网络IO。
  • LB01 – 一个Nginx服务器,用于Web及Apache前端的反向代理。所有的访问连接会通过nginx代理服务,被直接处理或分发到相应的Web服务器。LB01提供简单的负载均衡。
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。