セキュリティが重要であることは誰もが知っていますが、業界の傾向は最後の瞬間までセキュリティを追加しないことです。 Web アプリケーションを完全に保護することは不可能なので、わざわざ心配する必要はありません。間違っている。いくつかの簡単な手順を実行するだけで、PHP Web アプリケーションのセキュリティを大幅に向上させることができます。 始める前に このチュートリアルでは、独自の PHP Web アプリケーションにセキュリティを追加する方法を学びます。このチュートリアルでは、PHP Web アプリケーションの作成経験が少なくとも 1 年あることを前提としているため、PHP 言語の基本的な知識 (規則または構文) についてはここでは説明しません。目的は、構築する Web アプリケーションを保護する方法についてのアイデアを提供することです。 目標 このチュートリアルでは、SQL インジェクション、GET および POST 変数の操作、バッファ オーバーフロー攻撃、クロスサイト スクリプティング攻撃、ブラウザ内データ操作、リモート フォーム送信などの最も一般的なセキュリティ脅威に対する防御方法を説明します。 前提条件 このチュートリアルは、少なくとも 1 年のプログラミング経験を持つ PHP 開発者を対象に書かれています。 PHP の構文と規則については理解する必要がありますが、ここでは説明しません。ここで説明するルールの多くは他の言語や環境にも適用されるため、Ruby、Python、Perl などの他の言語を使用した経験のある開発者もこのチュートリアルから恩恵を受けるでしょう。 システム要件 PHP V4 または V5 および MySQL を実行する環境が必要です。 Linux、OS X、または Microsoft Windows を使用できます。 Windows を使用している場合は、WAMPServer バイナリをダウンロードし、Apache、MySQL、および PHP をマシンにインストールします。 セキュリティの簡単な紹介 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. 安全で完璧なコード $myUsername = 'tmyer'; $arrayUsers = array('tmyer', 'tom', 'tommy'); 'こんにちは' . $myUsername); ?> ただし、次のデータ要素にはすべて欠陥があります。 リスト 2. 安全でない欠陥のあるコード $myUsername = $_POST['username']; //汚染されています! $arrayUsers = array($myUsername, 'tom', 'tommy' ) / /tainted! define("GREETING", 'hello there' . $myUsername); //tainted! ?> 最初の変数 $myUsername はなぜですか?これはフォーム POST から直接取得されるためです。ユーザーはこの入力フィールドに任意の文字列を入力できます。これには、ファイルを駆除したり、以前にアップロードしたファイルを実行したりする悪意のあるコマンドも含まれます。 「A ~ Z の文字のみを受け入れるクライアント側 (JavaScript) フォーム検証スクリプトを使用すれば、この危険を回避できないのですか?」と疑問に思われるかもしれません。はい、これは常に有益なステップですが、後で説明するように、誰でもあらゆるフォームを自分のマシンにダウンロードし、変更して、必要なものを再送信できます。 解決策は簡単です。サニタイズコードは $_POST['username'] で実行する必要があります。これを行わないと、(配列や定数などで) $myUsername を使用するたびに、これらのオブジェクトが汚染される可能性があります。 ユーザー入力をサニタイズする簡単な方法は、正規表現を使用して処理することです。この例では、文字のみが受け入れられることが想定されています。文字列を特定の文字数に制限したり、すべての文字を小文字にすることを要求したりすることも良いアイデアかもしれません。 リスト 3. ユーザー入力を安全にする $myUsername = cleanInput($_POST['username']) //clean! $arrayUsers = array($myUsername, 'tom', ' tommy' ); //クリーン! 関数 cleanInput($input){ $clean = preg_replace ("/[^a-z]/", "", $clean); $clean = substr($clean,0,12) } ?> ルール 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 = (isset($_POST['username']) ? $_POST['username']:''); //難読化されていないコード $input = ''; $input = $_POST['username']){ $input = ' ' ; } ?> 2 番目の明確なコード スニペットでは、$input に欠陥があり、安全に処理する前にクリーンアップする必要があることが簡単にわかります。 ルール 4: 「多層防御」は新しい魔法の武器です このチュートリアルでは、フォームを処理する PHP コードで必要な措置を講じながら、オンライン フォームを保護する方法を例を使用して説明します。同様に、PHP 正規表現を使用して GET 変数が完全に数値であることを確認した場合でも、SQL クエリでエスケープされたユーザー入力が使用されることを確認する手順を実行できます。 多層防御は良いアイデアであるだけでなく、深刻な問題に巻き込まれないようにします。 基本的なルールについて説明したので、最初の脅威である SQL インジェクション攻撃を見てみましょう。 SQL インジェクション攻撃を防ぐ SQL インジェクション攻撃では、ユーザーはフォームまたは GET クエリ文字列を操作することによってデータベース クエリに情報を追加します。たとえば、単純なログイン データベースがあるとします。このデータベースの各レコードには、ユーザー名フィールドとパスワード フィールドがあります。ユーザーがログインできるようにするログイン フォームを作成します。 チェックリスト 5. 簡単なログインフォーム
この一連の操作は少し厳密すぎると思われるかもしれません。結局のところ、16 進文字列には、外国語で文字を印刷するなど、正当な用途があります。 16 進正規表現をどのように展開するかはあなた次第です。より良い戦略は、1 行に 16 進文字列が多すぎる場合、または文字列が特定の文字数 (128 や 255 など) を超えた場合にのみ 16 進文字列を削除することです。
クロスサイト スクリプティング攻撃
クロスサイト スクリプティング (XSS) 攻撃では、多くの場合、悪意のあるユーザーが (または他のユーザー入力方法を通じて) フォームに情報を入力し、悪意のあるクライアント側のタグを挿入します。プロセスまたはデータベース内で。たとえば、サイトに訪問者が名前、電子メール アドレス、簡単なメッセージを残せる簡単なゲストブック プログラムがあるとします。悪意のあるユーザーは、この機会を利用して、他のユーザーにとって不適切な画像やユーザーを別のサイトにリダイレクトする JavaScript など、短いメッセージ以外のものを挿入したり、Cookie 情報を盗んだりする可能性があります。
幸いなことに、PHP には、HTML タグで囲まれたコンテンツを削除できるstrip_tags() 関数が用意されています。また、strip_tags() 関数を使用すると、
や など、許可されるタグのリストを提供できます。 リスト 16 は、前の例を基にした例を示しています。 リスト 16. ユーザー入力から HTML タグを削除する if ($_POST['submit'] == "go"){ //strip_tags $name =trip_tags($_POST['name ' ]); $name = substr($name,0,40); // 潜在的な 16 進文字を削除します $name = cleanHex($name); // 処理を続行します。 } 関数cleanHex($input){ $clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "",$input); return $clean ; } ?> セキュリティの観点から、公開ユーザー入力にはstrip_tags()を使用する必要があります。フォームが保護領域 (コンテンツ管理システムなど) にあり、ユーザーがタスク (Web サイトの HTML コンテンツの作成など) を正しく実行することを信頼している場合、strip_tags() の使用は不要であり、生産性に影響を与える可能性があります。 もう 1 つの質問: 投稿に対するコメントやゲスト登録エントリなどのユーザー入力を受け入れ、この入力を他のユーザーに表示する必要がある場合は、応答を PHP の htmlspecialchars() 関数に入れる必要があります。この関数は、アンパサンド、< > 記号を HTML エンティティに変換します。たとえば、アンパサンド (&) は & になります。この場合、悪意のあるコンテンツがフロントエンドのstrip_tags()処理を逃れたとしても、バックエンドのhtmlspecialchars()によって処理されます。 ブラウザ内データ操作 ユーザーがページ上のヘッダー要素やフォーム要素を改ざんできるようにするブラウザー プラグインのクラスがあります。 Mozilla プラグインである Tamper Data を使用すると、多くの隠しテキスト フィールドを持つ単純なフォームを簡単に操作して、PHP や MySQL にコマンドを送信できます。 ユーザーはフォームで [送信] をクリックする前に、データの改ざんを開始できます。フォームを送信すると、フォーム データ フィールドのリストが表示されます。データの改ざんを使用すると、ユーザーはこのデータを改ざんでき、ブラウザはフォームの送信を完了します。 前に作成した例に戻りましょう。文字列の長さがチェックされ、HTML タグが削除され、16 進文字が削除されました。ただし、以下に示すように、いくつかの隠しテキスト フィールドが追加されています。 リスト 17. 隠し変数 if ($_POST['submit'] == "go"){ //strip_tags $ name =trip_tags($_POST['name']); $name = substr($name,0,40) //潜在的な 16 進文字を削除します $name = cleanHex($name);処理中.... } function cleanHex($input){ $clean = preg_replace("![][xX]([A-Fa-f0-9]{1,3})!", "" ,$input); return $clean; ?> 隠し変数の 1 つがテーブル名を公開していることに注意してください。値 create を含むアクション フィールドも表示されます。基本的な SQL の経験がある人なら、これらのコマンドがおそらくミドルウェアの SQL エンジンを制御していることがわかります。大混乱を引き起こしたい人は、テーブル名を変更するか、削除などの別のオプションを提供するだけで済みます。 図 1 は、データ改ざんがもたらす可能性のある損害の範囲を示しています。データ改ざんにより、ユーザーはフォーム データ要素だけでなく、HTTP ヘッダーや Cookie にもアクセスできることに注意してください。 図 1. データ改ざんウィンドウ このツールを防御する最も簡単な方法は、どのユーザーもデータ改ざん (または同様のツール) を使用する可能性が高いと想定することです。システムがフォームを処理し、フォームを専用のロジックに送信するために必要な最小限の情報のみを提供します。たとえば、登録フォームは登録ロジックにのみ送信する必要があります。 共通のフォーム処理関数を構築し、多くのページがこの共通ロジックを使用している場合はどうなるでしょうか?隠し変数を使用してフローを制御するとどうなるでしょうか?たとえば、非表示のフォーム変数で、書き込むデータベース テーブルや使用するファイル リポジトリを指定できます。オプションは 4 つあります: 何も変更せず、システムに悪意のあるユーザーがいないことを祈ります。 非表示のフォーム変数の使用を避けるために、より安全な専用フォーム処理関数を使用するように関数を書き換えます。 md5() またはその他の暗号化メカニズムを使用して、隠しフォーム変数内のテーブル名またはその他の機密情報を暗号化します。 PHP 側でそれらを復号化することを忘れないでください。 略語やニックネームを使用して値の意味を曖昧にし、PHP フォーム処理関数でこれらの値を変換します。たとえば、users テーブルを参照したい場合は、u または任意の文字列 (u8y90x0jkL など) を使用して参照できます。 後の 2 つのオプションは完璧ではありませんが、ユーザーがミドルウェア ロジックやデータ モデルを簡単に推測するよりははるかに優れています。 今残っている質問は何ですか?リモートフォーム送信。 リモートフォーム送信 Webの利点は、情報やサービスを共有できることです。欠点は、情報やサービスの共有です。何の躊躇もなく物事を行う人もいます。 フォームを例に挙げてみましょう。誰でも Web サイトにアクセスし、ブラウザ上で [ファイル] > [名前を付けて保存] を使用してフォームのローカル コピーを作成できます。次に、完全修飾 URL (formHandler.php ではなく、フォームはこのサイトにあるため http://www.yoursite.com/formHandler.php) を指すようにアクション パラメーターを変更し、必要なことを実行できます。変更を行った場合は、「送信」をクリックすると、サーバーはこのフォーム データを法的な通信フローとして受信します。 まず、$_SERVER['HTTP_REFERER'] をチェックして、リクエストが自分のサーバーからのものであるかどうかを確認することを検討してください。この方法では、ほとんどの悪意のあるユーザーをブロックできますが、最も高度なハッカーをブロックすることはできません。これらの人々は、ヘッダー内の参照元情報を改ざんして、フォームのリモート コピーをサーバーから送信されたように見せかけるほど賢いのです。 リモート フォームの送信を処理するより良い方法は、一意の文字列またはタイムスタンプに基づいてトークンを生成し、このトークンをセッション変数とフォームに入れることです。フォームを送信した後、2 つのトークンが一致するかどうかを確認します。一致しない場合は、誰かがフォームのリモート コピーからデータを送信しようとしていることがわかります。 ランダム トークンを作成するには、以下に示すように、PHP の組み込み md5()、uniqid()、および rand() 関数を使用できます。 リスト 18. リモート フォーム送信に対する防御 session_start () ; if ($_POST['submit'] == "go"){ //トークンをチェック if ($_POST['token'] == $_SESSION['token']){ // strip_tags $ name = strip_tags( 'name']); uniqid(rand(), true)); $_SESSION['token'] = $token; function cleanHex($input){ $clean = preg_replace("![][xX]([A-Fa- f0-9]{1,3})!", "",$input ;label for="name">名前
セッション データは移行できないため、 PHP のサーバー間。誰かがあなたの PHP ソース コードを取得し、それを自分のサーバーに移動し、あなたのサーバーに情報を送信したとしても、あなたのサーバーが受け取るのは、空または不正な形式のセッション トークンと、最初に提供されたフォーム トークンだけです。これらは一致しないため、リモート フォームの送信は失敗します。
結論
このチュートリアルでは多くの問題について説明しました:
SQL インジェクションの問題を防ぐために mysql_real_escape_string() を使用します。
正規表現と strlen() を使用して、GET データが改ざんされていないことを確認します。
正規表現と strlen() を使用して、ユーザーが送信したデータがメモリ バッファーをオーバーフローしないようにします。
strip_tags() と htmlspecialchars() を使用して、ユーザーが有害な可能性のある HTML タグを送信しないようにします。
データ改ざんなどのツールによるシステムの侵害を防ぎます。
一意のトークンを使用して、ユーザーがリモートからサーバーにフォームを送信できないようにします。
このチュートリアルでは、ファイル インジェクション、HTTP ヘッダー スプーフィング、その他の脆弱性などのより高度なトピックについては説明しません。ただし、ここで学んだことは、現在のプロジェクトをより安全にするために十分なセキュリティをすぐに追加するのに役立ちます。
参考資料
学習
Zend.com で役立つ PHP 101 チュートリアルを見つけてください。
Chris Shiflett の『Essential PHP Security』のコピーを入手してください。彼が行う紹介は、このチュートリアルよりもはるかに詳細です。
Simson Garfinkel の『Web セキュリティ、プライバシー、コマース』のコピーを入手してください。
PHP セキュリティ コンソーシアムの詳細をご覧ください。
「PHP セキュリティ上の間違いトップ 7」を読んでください。
developerWorks の「推奨 PHP 読書リスト」をチェックしてください。
developerWorks の記事「PHP の監査、パート 1: register_globals について」を読んでください。
PHP セキュリティ HOWTO ウェブキャストをチェックしてください。
PHP について詳しくは、IBM developerWorks の PHP プロジェクト リファレンスを参照してください。
developerWorks の技術イベントや Web キャストにご注目ください。
世界中の IBM オープンソース開発者向けの今後のカンファレンス、インサイダー プレビュー、Web キャスト、その他のイベントについて学びます。
developerWorks のオープンソース ゾーンにアクセスしてください。ここには、オープンソース テクノロジーを使用した開発や IBM 製品での使用に役立つ、豊富なハウツー情報、ツール、プロジェクトの更新情報が含まれています。
ソフトウェア開発者間の興味深いインタビューやディスカッションを聞きたい場合は、developerWorks ポッドキャストを必ずチェックしてください。
製品とテクノロジーを入手
Windows ユーザーは WAMPServer をダウンロードできます。
PHP を使用して次の開発プロジェクトを構築します。
ダウンロードまたは DVD として入手できる IBM 試用版ソフトウェアを使用して、次のオープンソース開発プロジェクトを改善します。
ディスカッション
developerWorks ブログに参加して、developerWorks コミュニティに参加してください。
著者について
Thomas Myer は、情報アーキテクチャ、Web アプリケーション開発、および XML コンサルティングを専門とする、テキサス州オースティンにある Web コンサルティング会社、Triple Dog Dare Media の創設者および主要人物です。彼は、『No Nansense XML Web Development with PHP』 (SitePoint 発行) の著者です。
http://www.bkjia.com/PHPjc/317197.html www.bkjia.com 本当 http://www.bkjia.com/PHPjc/317197.html 技術記事 セキュリティが重要であることは誰もが知っていますが、業界の傾向は最後の瞬間までセキュリティを追加しないことです。 Web アプリケーションを完全にセキュリティで保護することは不可能なので、なぜわざわざ苦労する必要があるのでしょうか...