とも呼ばれるようになっています。
Webアプリケーションは、作り方を間違えると「インジェクション」(コードや特殊文字などの挿入)により、セキュリティ上重大な問題を簡単に作れてしまいます。クロスサイトスクリプティングはインジェクション攻撃の中でも最も防御が複雑で難しいセキュリティ上の問題です。
なぜクロスサイトスクリプティングは危険な脆弱性なのか?
Webアプリケーションプログラミングに慣れていない方は、インジェクト(挿入)されたJavaScriptコードが実行されて何が困るのか解らないかもしれません。JavaScriptはブラウザに保存されたクッキーにアクセスしたり、ブラウザに出力されるページを変更できます。「任意のJavaScriptコードを挿入できる」ことは「クッキーの取得」「ページの内容を書き換え」が可能になることを意味します。
クッキーはHTTPセッション管理に利用されるセッションIDに利用されます。「クッキーの取得」は「セッションIDの取得」が可能であることを意味します。つまり、ログイン済みの第三者のアカウントを不正に利用可能になります。詳しい説明は省略しますが、匿名性を維持しつつセッションIDの収集をするは非常に簡単です。
例えば、ログインページがクロスサイトスクリプティングに脆弱であった場合は、ユーザIDとパスワードを簡単に盗み取れます。JavaScriptはドキュメントの任意ノード(構成要素)を書き換えることができます。ログイン名、パスワードを記述したフォームを書き換えて、攻撃者のサーバに送信するページに置き換えられます。有名なサイトではあり得ないことのように思いますが、PayPalのログインページはクロスサイトスクリプティングに脆弱でした。
なぜクロスサイトスクリプティングは無くならないのか?
この連載ではSQLインジェクションは簡単に防げると書きました。SQLインジェクションはクエリ実行時にスドアドプロシージャを利用するか、すべての変数を適切な方法でエスケープするだけで完全に防げます[1]。しかし、クロスサイトスクリプティング脆弱性は簡単には防げません。
クロスサイトスクリプティングが無くならない理由
- すべての出力をエスケープできない
- 出力する場所によって適切なエスケープ方法が異なる
- どの変数がユーザからの入力を含んでいるか分かりづらい
- クライアント側(JavaScript)の問題でも問題が発生する
クロスサイトスクリプティングはSQLインジェクションと異なり、エスケープしてはならない場合やエスケープ方法が異なる場合があります。エスケープしてはならない場合、変数にユーザ入力が含まれているか含まれていないのか、正確に分かっていなければならないですが、システムが設定していると思いがちな変数にユーザ入力が含まれている場合もあります。REQUEST_URI, REFERER, X_FORWARDED_FORなどのWebサーバが設定する値やHTTPヘッダの値は、ユーザが自由に設定できる値なので直接出力してはならない変数です。
ユーザ入力を一旦別の変数に代入すると、その変数が危険な変数であることが分かりづらくなります。ユーザ入力を含む変数名が長いからといって短い名前の変数に代入して利用するコードは、危険性が高くなります。
さらに、最近AJAXの普及により、クライアントで複雑なJavaScriptを実行するアプリケーションが増えています。JavaScriptを利用している場合、サーバ側のコードと無関係にクロスサイトスクリプティングに脆弱となる場合があります。
実際の脆弱性はこの例のほど単純ではありませんが、JavaScriptのコードがクロスサイトスクリプティング脆弱性を作ってしまうことが分かると思います。