PHP は、ほとんどのサーバー システムのファイルとディレクトリのアクセス許可に関するセキュリティ メカニズムに準拠しています。これにより、管理者はファイル システム内でどのファイルを読み取り可能にするかを制御できます。グローバルに読み取り可能なファイルには特別な注意を払い、すべての許可されたユーザーによるこれらのファイルの読み取りが安全であることを確認する必要があります。
PHP はユーザーレベルでファイルシステムにアクセスするように設計されているため、/etc/passwd などのシステムファイルを読み取り、ネットワーク接続を変更し、大量の印刷ジョブを送信するための PHP コードを作成することは完全に可能です。等したがって、PHP コードが適切なファイルを読み書きしていることを確認する必要があります。
以下のコードを見てください。ユーザーはホーム ディレクトリ内のファイルを削除したいと考えています。このシナリオでは、ファイル システムが Web インターフェイスを通じて管理されているため、Apache ユーザーがユーザー ディレクトリ内のファイルを削除する権限を持っていると仮定します。
例 #1 変数のセキュリティ チェックの実行に失敗すると、次のような問題が発生します...
<?php // 从用户目录中删除指定的文件 $username = $_POST['user_submitted_name']; $userfile = $_POST['user_submitted_filename']; $homedir = "/home/$username"; unlink ("$homedir/$userfile"); echo "The file has been deleted!"; ?>
ユーザー名とファイル名の変数はユーザー フォームから送信できるため、他の人のユーザー名とファイル名を送信したり、削除すべきものを削除したりすることもできます。文書は削除されません。この場合、他の認証方法を考慮する必要があります。送信された変数が「../etc/」と「passwd」だった場合に何が起こるかを考えてみましょう。上記のコードは次と同等です:
例 #2…ファイル システム攻撃
<?php // 删除硬盘中任何 PHP 有访问权限的文件。如果 PHP 有 root 权限: $username = $_POST['user_submitted_name']; // "../etc" $userfile = $_POST['user_submitted_filename']; // "passwd" $homedir = "/home/$username"; // "/home/../etc" unlink("$homedir/$userfile"); // "/home/../etc/passwd" echo "The file has been deleted!"; ?>
このような問題を防ぐための重要な対策が 2 つあります。
PHP Web ユーザーに非常に限定された権限のみを与えます。
送信されたすべての変数を確認します。
改善されたスクリプトは次のとおりです:
例 #3 より安全なファイル名チェック
<?php // 删除硬盘中 PHP 有权访问的文件 $username = $_SERVER['REMOTE_USER']; // 使用认证机制 $userfile = basename($_POST['user_submitted_filename']); $homedir = "/home/$username"; $filepath = "$homedir/$userfile"; if (file_exists($filepath) && unlink($filepath)) { $logstring = "Deleted $filepath\n"; } else { $logstring = "Failed to delete $filepath\n"; } $fp = fopen("/home/logging/filedelete.log", "a"); fwrite ($fp, $logstring); fclose($fp); echo htmlentities($logstring, ENT_QUOTES); ?>
ただし、これにはまだ欠陥があります。認証システムでユーザーが独自のログイン ユーザー名を作成できる場合に、ユーザーがユーザー名として「../etc/」を使用することを選択した場合、システムは再び失敗します。したがって、チェックを強化する必要があります:
例 #4 より安全なファイル名チェック
<?php $username = $_SERVER['REMOTE_USER']; // 使用认证机制 $userfile = $_POST['user_submitted_filename']; $homedir = "/home/$username"; $filepath = "$homedir/$userfile"; if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) { die("Bad username/filename"); } //后略…… ?>
オペレーティング システムによっては、システムに接続されているデバイス (/dev/ または COM1) を含む、注意が必要なさまざまなファイルがあります。 、設定ファイル (/ect/ ファイルおよび .ini ファイル)、一般的に使用されるストレージ領域 (/home/ またはマイ ドキュメント) など。このため、多くの場合、すべてのアクセス許可を無効にし、明示的に許可されたアクセス許可のみを有効にするポリシーを確立する方が簡単です。