blog

システム管理者のために書かれた25のPHPセキュリティ・プラクティス

PHPは広く使われているオープンソースのサーバーサイドスクリプト言語です。Apache Web サービスにより、ユーザーは HTTP または HTTPS プロトコルを介してファイルやコンテンツにアクセ...

Jun 24, 2025 · 18 min. read
シェア

PHP は、広く使われているオープンソースのサーバーサイドスクリプト言語です。ウェブサービスは、ユーザーが HTTP や PS プロトコルでファイルやコンテンツにアクセスすることを可能にします。サーバーサイドスクリプティング言語の設定を誤ると、 さまざまな問題を引き起こす可能性があります。そのため、PHP の使用には注意が必要です。ここでは、システム管理者が PHP を安全に設定するための 25 の実践的な例を紹介します。

以下のサンプルPHP設定

  • DocumentRoot: /var/www/html
  • デフォルトのウェブサービス: Apache
  • デフォルトの PHP 設定ファイル: /etc/php.ini
  • デフォルトの PHP 拡張モジュール設定ディレクトリ: /etc/php.d/
  • PHP セキュリティ設定サンプルファイル: /etc/php.d/security.ini
  • OS: RHEL / CentOS / Fedora Linux
  • PHP サービス用のデフォルト TCP/UDP ポート: none

今日の午後に挙げたアクションのほとんどは、rootユーザーがbashやその他のモダンなシェルでアクションを実行できることを前提としています。

$ php -v 

サンプル出力:

PHP 5.3.3 (cli) (built: Oct 24 2011 08:35:41) 
 (c) 1997-2010 The PHP Group 
Zend Engine v2.3.0,  (c) 1998-2010 Zend Technologies 
$ cat /etc/redhat-release 

サンプル出力:

Red Hat Enterprise Linux Server release 6.1 (Santiago) 

#その1:他者を知る

PHP ベースのアプリケーションは、さまざまな攻撃に直面しています:

  • XSS: クロスサイトスクリプティングは、PHPウェブアプリケーションの脆弱点です。攻撃者はこれを利用してユーザー情報を盗むことができます。XSS攻撃から守るために、Apacheを設定したり、より安全なPHPコードを書くことができます!
  • ファイルアップロード:訪問者がサーバーにファイルを置くことができます。これは、例えばサーバーファイルやデータベースの削除、ユーザー情報へのアクセス、その他多くの問題を引き起こす可能性があります。PHPを使ってファイルアップロードを無効にしたり、より安全なコードを書くことができます。
  • ローカルおよびリモートのファイルを含む: 攻撃者は、リモートサーバーにファイルを開かせ、任意の PHP コードを実行させ、そのファイルをアップロードまたは削除してバックドアをインストールすることができます。これは、リモートファイル実行の設定を解除することで防ぐことができます。
  • eval():この関数は、文字列をあたかもPHPコードのように実行します。この関数は、攻撃者がサーバー上のコードやツールを隠すためによく使用されます。これは、 eval() 関数の呼び出しをキャンセルするように PHP を設定することで実現できます。
  • シースルト攻撃:この攻撃は、エンドユーザに現在のアカウントで不特定のアクションを実行させます。これはエンドユーザのデータと操作のセキュリティを脅かします。対象のエンドユーザのアカウントが管理者権限で使用されている場合、ウェブ・アプリケーション全体が危険にさらされます。

#その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ご覧ください。

#p#

#その3:PHPの情報漏洩対策

PHPの情報漏えいは、export_phpを削除することで制限することができます。etc/php.d/security.ini を以下のように編集します:

expose_php=Off 

expose_php は、サーバー上の PHP に関する情報 (バージョンを含む) を HTTP ヘッダに追加します。同時に、PHP のグローバルな統一識別子が公開されます。expose_phpが有効な場合は、以下のコマンドでPHPのバージョン情報を見ることができます:

$ curl -I http://..biz/.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  
... 

ServerTokens and ServerSignature directives in httpd.conf to hide Apache version Apache のバージョンとその他の情報も隠すことをお勧めします。

#4: ロード可能な PHP モジュールの最小化

# 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: リモートコード実行の無効化

allow_url_fopen=Off 
これに加えて、LB01を使用できるようにすることが推奨される。_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 では正しく動作しないかもしれません。また、PHP バージョン 5.3.x の magic_quotes_gpc フィルタリングは単純で非効率的なので無効にすることを推奨します。mysql_escape_string() や独自のフィルタリング関数を使用するほうがよいでしょう。

magic_quotes_gpc=Off 

#その9:POSTデータサイズの制御

HTTP POST は、ファイルをアップロードしたりフォームを送信したりするように、 Apache ウェブサーバにデータを送信するリクエストの一部としてクライアントによって一般的に使われます。攻撃者はサーバのリソースを消費するために非常に大きな POST リクエストを送ろうとします。etc/php.d/security.ini を以下のように編集して POST の最大サイズを制限してください:

; ここに信頼できる値を設定する 
post_max_size=1K 

最大サイズは1Kです。この設定はファイルのアップロードに影響します。大きなファイルをアップロードするには、この値を update_max_filesize より大きくする必要があります。

httpd.nfを以下のように編集して、Apacheで利用可能なリクエストメソッドを制限することをお勧めします:

<Directory /var/www/html> 
     <LimitExcept GET POST> 
         Order allow,deny 
     </LimitExcept> 
## Add rest of the config goes here... ## 
</Directory> 

#10位:リソースコントロール

各 PHP スクリプトの最大実行時間を設定します。また、要求されたデータの処理に使用される最大時間や、使用可能な最大メモリ量も制限することをお勧めします。

# 単位:秒 
max_execution_time = 30 
max_input_time = 30 
memory_limit = 40M 

#11: PHP用スホーシン・アドバンスド・プロテクション・システムのインストール

#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 の管理

; Enable cgi.force_redirect for security reasons in a typical *Apache+PHP-CGI/FastCGI* setup 
cgi.force_redirect=On 

#14: PHPのユーザとユーザグループのID

mod_fastcgi は、外部の FASTCGI サーバーに接続する Apache ウェブサービス用の cgi モジュールです。PHP が root 以外のユーザーで実行されていることを確認する必要があります。root または UID が 100 未満のユーザーを使用すると、 オペレーティングシステムのファイルにアクセスすることさえできます。PHPのCGIは、ApacheのsuEXECまたはmod_suPHPにより、 非特権ユーザーで実行することができます。suEXECは、Apacheが起動するCGIプログラムのユーザーIDで、 Apacheを実行しているユーザーのユーザー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 

リモートまたはローカルの FastCGI プロセスは、 spawn-fcgi で生成できます:

# spawn-fcgi -a .1 -p 9000 -u phpcgi -g phpcgi -f /usr/bin/php-cgi 

127.0.0.1:9000で動作するFastCGIを呼び出すように、Apache、Lighthttpd、またはWebサービスを設定できるようになりました。

#p#

#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: セッションパス

PHPセッションのユーザーには、次回以降の訪問のためにデータを保存する機能が提供されます。これにより、アプリケーションをよりカスタマイズしやすくし、魅力を高めることができます。セッションに関連するデータはすべて 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 セキュリティ情報を表示します。

#17: PHP、ソフトウェア、オペレーティングシステムが最新であること。

Linux、Apache、PHP、MySQL サーバーの保守で重要なことは、セキュリティパッチの更新です。PHPのセキュリティアップデートはすべて確認し、できるだけ早く更新する必要があります。以下のコマンドを使用します:

# yum update 
  
# apt-get update && apt-get upgrade 

注意: 最新のPHPバージョン情報はphp.netで確認してください!

#18: ファイルやディレクトリへのアクセス制限

var/www/htmlディレクトリの所有者も非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のセキュリティ拡張機能を使う

Linuxには、サービスプログラムの誤設定や脆弱性を防ぐための様々なセキュリティスキームがあります。可能な限り、SELinuxや他のLinuxセキュリティスキームを使用して、ネットワークやプログラムを制限してください。例えば、SELinux は Linux カーネルや Apache ウェブサービスに異なるセキュリティポリシーを提供します。次のコマンドを使用して、すべての 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 

#p#

#21: Mod_securityのインストール

ModSecurity はオープンソースの侵入検知・防止ウェブアプリケーションエンジンです。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 を実行してください。

#23: ファイアウォールによる送信接続の制限

/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-aware 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.0 --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. --dport 80 -j RETURN 
/sbin/iptables --append apache_user -p tcp --syn -d  66. --dport 80 -j RETURN 
/sbin/iptables --append apache_user -p tcp --syn -d  72. --dport 80 -j RETURN 
/sbin/iptables --append apache_user -p tcp --syn -d  72. --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 システム監視ツールを使用することをお勧めします。

#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を侵害した場合、同じサーバーの他のサービスにアクセスすることができます。しかし、上記の例では違います:

  • mysql1.lan.cyberciti.biz - MySQLデータベースサービス
  • mcache1.lan.cyberciti.biz - Memcached サービス。libevent または epoll を使って任意の数の接続に対応します。また、ノンブロッキングネットワーク IO を使用します。
  • LB01 - ウェブ用の Nginx サーバと Apache フロントエンドのリバースプロキシです。すべてのアクセス接続は直接処理されるか、nginx プロキシサービスを通して適切なウェブサーバに分配されます。
Read next

アプリケーション・セキュリティ管理の「ビッグ8

アプリケーションのセキュリティ設定、非標準のディレクトリやポートへのアプリケーションのインストール、アプリケーションのロック、P2Pサービスのセキュリティ保護など、8つの分野でアプリケーションを多角的かつ体系的に管理できます。

Jun 24, 2025 · 7 min read