始める前に
このチュートリアルでは、独自の PHP Web アプリケーションにセキュリティを追加する方法を学習します。このチュートリアルでは、PHP Web アプリケーションの作成経験が少なくとも 1 年あることを前提としているため、PHP 言語の基本的な知識 (規則または構文) についてはここでは説明しません。目的は、構築する Web アプリケーションを保護する方法を理解していただくことです。
目標
このチュートリアルでは、SQL インジェクション、GET および POST 変数の操作、バッファ オーバーフロー攻撃、クロスサイト スクリプティング攻撃、ブラウザ内データ操作、リモート フォーム送信などの最も一般的なセキュリティ脅威から保護する方法について説明します。
前提条件
このチュートリアルは、少なくとも 1 年のプログラミング経験を持つ PHP 開発者を対象に書かれています。 PHP の構文と規則については理解する必要がありますが、ここでは説明しません。ここで説明するルールの多くは他の言語や環境にも適用されるため、Ruby、Python、Perl などの他の言語を使用した経験のある開発者もこのチュートリアルから恩恵を受けるでしょう。
セキュリティの簡単な紹介
Web アプリケーションの最も重要な部分は何ですか?誰が質問に答えるかによって、この質問に対する答えは異なる場合があります。ビジネスマンは信頼性と拡張性を必要としています。 IT サポート チームは、堅牢で保守可能なコードを必要としています。エンドユーザーは、タスクを実行する際に美しいユーザー インターフェイスと高いパフォーマンスを必要とします。しかし、答えが「セキュリティ」であれば、それが Web アプリケーションにとって重要であることに誰もが同意するでしょう。
しかし、ほとんどの議論はここで終わります。セキュリティはプロジェクトのチェックリストに含まれていますが、多くの場合、プロジェクトが納品されるまで対処されません。このアプローチを採用している Web アプリケーション プロジェクトの数は驚異的です。開発者は何か月もかけて取り組み、最後にセキュリティ機能を追加して、Web アプリケーションを一般公開できるようにしました。
セキュリティ機能が追加される前にコードが検査され、単体テストされ、より大きなフレームワークに統合されているため、結果は混乱したり、再作業が必要になったりすることがよくあります。セキュリティを追加すると、主要なコンポーネントが動作しなくなる場合があります。セキュリティを統合すると、スムーズな (ただし安全ではない) プロセスに余分な負担やステップが追加されます。
このチュートリアルは、PHP Web アプリケーションにセキュリティを統合するための優れた方法を提供します。ここでは、いくつかの一般的なセキュリティのトピックについて説明し、その後、主要なセキュリティの脆弱性とその解決方法について詳しく説明します。このチュートリアルを完了すると、セキュリティについてより深く理解できるようになります。
トピックには以下が含まれます:
SQL インジェクション攻撃
GET 文字列の操作
バッファ オーバーフロー攻撃
クロスサイト スクリプティング攻撃 (XSS)
ブラウザ内データ操作
リモート フォーム送信
Web セキュリティ 101
セキュリティの実装についての議論詳細については、Web アプリケーションのセキュリティを高レベルの観点から議論するのが最善です。このセクションでは、作成する Web アプリケーションの種類に関係なく、心に留めておくべきセキュリティ哲学の基本原則をいくつか紹介します。これらのアイデアの中には、Chris Shiflett (PHP セキュリティーに関する著書は貴重な宝庫です) から得たもの、Simson Garfinkel (「参考文献」を参照) から得たもの、そして長年蓄積された知識から得たものもあります。
ルール 1: 外部データや入力を決して信頼しない
Web アプリケーションのセキュリティについて最初に認識しなければならないことは、外部データは信頼すべきではないということです。外部データには、プログラマによって PHP コードに直接入力されないデータが含まれます。他のソースからのデータ (GET 変数、フォーム POST、データベース、構成ファイル、セッション変数、Cookie など) は、セキュリティを確保するための手順が講じられるまで信頼できません。
たとえば、次のデータ要素は PHP で設定されているため安全であると考えられます。
リスト 1. 安全で完璧なコード
[php]$myUsername = 'tmyer';
$arrayUsers = array('tmyer', 'tom', 'tommy');
define("GREETING", 'hello there' . $myUsername); [/php]
ただし、次のデータ要素にはすべて欠陥があります。 、 リスト 2. 安全でない欠陥のあるコード
[PHP] $ myusername = $ _post ['username'] // 汚染されています
$ arrayusers = Array ($ myusername, 'tom', 'tommy'); !
define("GREETING", 'hello there' . $myUsername); //tainted! [/php]
最初の変数 $myUsername が間違っているのはなぜですか?これはフォーム POST から直接取得されるためです。ユーザーはこの入力フィールドに任意の文字列を入力できます。これには、ファイルを駆除したり、以前にアップロードしたファイルを実行したりする悪意のあるコマンドも含まれます。 「A ~ Z の文字のみを受け入れるクライアント側 (JavaScript) フォーム検証スクリプトを使用すれば、この危険を回避できないのですか?」と疑問に思われるかもしれません。はい、これは常に有益なステップですが、後で説明するように、誰でもあらゆるフォームを自分のマシンにダウンロードし、変更して、必要なものを再送信できます。
解決策は簡単です。サニタイズ コードは $_POST['username'] で実行する必要があります。これを行わないと、(配列や定数などで) $myUsername を使用するたびに、これらのオブジェクトが汚染される危険があります。
ユーザー入力をサニタイズする簡単な方法は、正規表現を使用して処理することです。この例では、文字のみが受け入れられることが想定されています。文字列を特定の文字数に制限したり、すべての文字を小文字にすることを要求したりすることも良いアイデアかもしれません。リスト 3. ユーザー入力が安全になります。 ; //clean!
define("GREETING", 'hello there' . $myUsername); //clean!
function cleanInput($input){
$clean = strto lower($input) );
$clean = preg_replace(" /[^a-z]/", "", $clean);
$clean = substr($clean,0,12);
return $clean;
}[/php]
ルール 2: セキュリティを困難にするものを無効にする PHP セットアップの実装
ユーザー入力が信頼できないことがわかったので、マシン上での PHP の構成方法も信頼すべきではないことも理解する必要があります。たとえば、register_globals が無効になっていることを確認してください。 register_globals が有効な場合、$variable を使用して GET または POST 文字列を同じ名前に置き換えるなどの不注意な行為が可能になります。この設定を無効にすると、PHP は正しい名前空間の正しい変数を参照するように強制します。フォーム POST から変数を使用するには、$_POST['variable'] を引用符で囲む必要があります。こうすることで、この特定の変数を Cookie、セッション、または GET 変数と間違えることがなくなります。
2 番目に確認する設定は、エラー報告レベルです。開発中はできるだけ多くのエラー レポートを取得したいと考えますが、プロジェクトを納品するときは、エラーを画面に表示するのではなくログ ファイルに記録したいと考えます。なぜ?悪意のあるハッカーは、エラー報告情報 (SQL エラーなど) を使用して、アプリケーションが何を行っているかを推測する可能性があるためです。この種の偵察は、ハッカーがアプリケーションに侵入するのに役立つ可能性があります。この脆弱性を解決するには、php.ini ファイルを編集して error_log エントリの適切な保存先を指定し、display_errors を Off に設定します。
ルール 3: 理解できない場合、保護することはできません
一部の開発者は、奇妙な構文を使用したり、ステートメントを非常に厳密に編成して、短くても曖昧なコードを形成します。このアプローチは効率的かもしれませんが、コードが何をしているのかを理解していないと、コードを保護する方法を決定できません。
たとえば、以下の 2 つのコードのうちどれが好きですか?リスト 4. コードを保護しやすくする
$input = ”;
if (isset($_POST['ユーザー名'])){
$input = $_POST['ユーザー名'];
}else{
$ input = ”;
}[/php]
2 番目の明確なコード スニペットでは、$input に欠陥があり、安全に処理する前にクリーンアップする必要があることが簡単にわかります
ルール 4: 「多層防御」新しい魔法の武器
このチュートリアルでは、フォームを処理する PHP コードで必要な措置を講じながらオンライン フォームを保護する方法を説明する例を示します。同様に、GET 変数が完全に数値であることを確認するために PHP 正規表現を使用する場合でも、 SQL クエリがエスケープされたユーザー入力を使用するようにするための措置を講じることもできます
多層防御は良いアイデアであるだけでなく、深刻な問題に巻き込まれないようにするための手段です
基本的なルールについて説明したので、見てみましょう。最初の脅威: SQL インジェクション攻撃
SQL インジェクション攻撃の防止
。SQL インジェクション攻撃では、ユーザーはフォームまたは GET クエリ文字列を操作してデータベース クエリに情報を追加します。たとえば、単純なログイン データベースについて考えてみましょう。このデータベースには、ユーザー名フィールドとパスワードフィールドがあります。ユーザーがログインできるようにするログインフォームを作成します。
リスト 5. 単純なログインフォーム
[php]