PHP は、動的 Web ページを迅速に開発するための素晴らしい言語です。 PHP には、動的宣言を必要としないなど、初心者プログラマーにとって使いやすい機能もあります。ただし、これらの特性により、プログラマが Web アプリケーションにセキュリティ上の脆弱性を誤って侵入させてしまう可能性があります。一般的なセキュリティ メーリング リストには、PHP アプリケーションの実証済みの脆弱性が多数ありますが、PHP アプリケーションによくある基本的な脆弱性の種類を理解すれば、それが他の言語と同じくらい安全であることがわかります。
この記事では、セキュリティの脆弱性につながる可能性のある、PHP プログラムの一般的な欠陥をいくつか詳しく紹介します。それぞれの特定の欠陥を、何をしてはいけないのか、どのように悪用するのかを示すことで、これらの特定の欠陥を回避する方法だけでなく、なぜこれらの間違いがセキュリティの脆弱性につながるのかについても理解していただけると幸いです。
考えられるすべての落とし穴を理解すると、PHP アプリケーションで同じ間違いを犯すことを避けることができます。
セキュリティは製品ではなくプロセスです。アプリケーション開発プロセスにセキュリティに配慮したアプローチを採用すると、より緊密で堅牢なコードを作成できます。
未検証の入力欠陥
最も一般的な PHP セキュリティ脆弱性の 1 つは、検証されていない入力エラーです。データを提供するユーザーはまったく信頼できません。 Web アプリケーションのユーザーの一部には悪意があるため、Web アプリケーションのユーザーは全員悪意があると想定する必要があります。未検証または誤って検証された入力は、いくつかの脆弱性の悪用の原因となります。これについては、この記事の後半で説明します。
たとえば、UNIX cal コマンドを呼び出して、ユーザーがカレンダーを表示し、指定した月を表示できるようにする次のコードを作成できます。
$month = $_GET['month'];
$year = $_GET['year'];
exec("cal $month $year", $result);
「
」を印刷"; <p> foreach ($result as $r) { print "$r<br>"; }</p> <p> print "</p>
";
$_GET[month] 変数と $_GET[year] 変数がいかなる方法でも検証されていないため、このコードにはセキュリティ上の脆弱性があります。特定の月が 1 から 12 の間であり、適切な 4 桁の年が指定されている限り、アプリは完全に動作します。ただし、悪意のあるユーザーが year パラメータに「;ls -la」を追加すると、サイトの HTML ディレクトリ リストが表示される可能性があります。非常に悪質なユーザーは、year パラメータに「;rm -rf *」を追加し、Web サイト全体を削除する可能性があります。
このエラーを修正する適切な方法は、ユーザーから受け取る入力が期待どおりであることを確認することです。このようなエラーに対して JavaScript 検証を使用するのではなく、開発者は独自の形式の JavaScript を作成したり、そのような検証メソッドを処理するための JavaScript を無効にしたりすることが簡単です。入力した月と年が数値であることを確認するには、以下に示すように PHP コードを追加する必要があります。
$month = $_GET['month'];
$year = $_GET['year'];
if (!preg_match("/^[0-9]{1,2}$/", $month)) die("悪い月です。再入力してください。");
if (!preg_match("/^[0-9]{4}$/", $year)) die("厄年です。再入力してください。");
exec("cal $month $year", $result);
「
」を印刷"; <p> foreach ($result as $r) { print "$r<br>"; }</p> <p> print "</p>
";
アプリケーションや入力を実行しているサーバーに影響を与える入力をユーザーが提供することを心配する必要はなく、コードを安全に使用できます。正規表現は、入力を検証するための優れたツールです。習得するのは難しいですが、この状況では非常に役立ちます。
予想されるデータと一致しないデータを拒否することで、ユーザーが指定したデータを常に検証する必要があります。有害であることがわかっていても、予期されるデータを受け入れるメソッドは決して使用しないでください。このメソッドはセキュリティ上の脆弱性の一般的な原因です。場合によっては、悪意のあるユーザーが、ヌル文字を使用して不正な入力を隠すなどして、この問題を回避できることがあります。このような入力はチェックを通過しますが、それでも悪影響を及ぼします。
入力を検証するときは、可能な限り厳密にする必要があります。含める必要のない文字がある場合は、可能であればそれらの不要な文字を削除するか、入力を完全に拒否する必要があります。
アクセス制御の欠陥
もう 1 つの欠陥は、必ずしも PHP アプリケーションに限定されるわけではありませんが、それでも重要ですが、アクセス制御の脆弱性のタイプです。この欠陥は、構成設定の変更や機密情報の表示を許可する管理ページなど、アプリケーションの一部が特定のユーザーに制限されている場合に発生します。
PHP アプリケーションの各ページの読み込みを制限する各ユーザーのアクセス権を確認する必要があります。インデックス ページでユーザーの証明書のみを確認すると、悪意のあるユーザーが「より深い」ページに直接リンクし、証明書の確認プロセスをスキップする可能性があります。
たとえば、Web サイトにユーザーを攻撃するための予測可能な IP アドレスまたは固定 IP アドレスがある場合、そのユーザーのベース IP アドレスとユーザー名へのアクセスを制限することで、プログラムにセキュリティ層を追加すると有利です。制限された Web ページを、apache.htaccess ファイルで保護された別のディレクトリに配置することもお勧めします。
構成ファイルを Web アクセス ディレクトリの外に置きます。構成ファイルにはデータベースのパスワードやその他の情報が含まれており、悪意のあるユーザーがサイトに侵入したり侵害したりするために使用される可能性があります。リモート ユーザーがこれらのファイルにアクセスすることは絶対に許可しないでください。 PHP の include 関数を使用して、Web にアクセスできないディレクトリのファイルを含めます。管理者のエラーによりディレクトリが Web からアクセスされた場合、これには「negate everything」を含む .htaccess ファイルが含まれる可能性があります。多層セキュリティは冗長ではありますが、良い点です。