|
|
対策遅らせるHTMLエンコーディングの「神話」
狙われるWebアプリケーション【第2回】
京セラコミュニケーションシステム セキュリティ事業部 副事業部長 徳丸 浩(とくまる ひろし) クロスサイト・スクリプティングという言葉は元々,WebアプリケーションのHTMLエンコード漏れなどを利用することによって第三者にJavaScriptを実行させる手法を指す。広義では,HTMLのエンコードによる画面改変などを含むこともある。 前回述べたように,クロスサイト・スクリプティングのぜい弱性はWebアプリケーションに見付かるぜい弱性の半分以上を占める。数年前から指摘されているにもかかわらず,一向になくならない。その理由として,クロスサイト・スクリプティング対策あるいはHTMLエンコード注1)に対する「神話」があり,正しい対策の普及を遅らせているように思う。その「神話」の数々について説明しよう。 注1)実体参照(entity reference)というのが正式だが,あまり普及していない用語なので,HTMLエンコードという用語を用いる 「すべからくHTMLエンコードすべし」が鉄則HTMLエンコードというのは,例えば「&」「<」「>」「"」といった,HTMLとして特殊な意味を持つ文字(特殊文字またはメタ文字)を,意味を持たない別の文字列に置換することである。前述の特殊文字なら,「&」「<」「>」「"」に置換する。前回も紹介したエスケープ処理である。この処理を怠ると,メタ文字として扱われるデータの入力を許すことになる。これが,クロスサイト・スクリプティングの原理だ。JavaScript実行による典型的な攻撃は,第三者のCookieを盗み出して行うセッション・ハイジャックである。米国のYahoo!メールで発生したYamannerワーム(参考:「Yahoo!メールのウィルスが悪用したのは『XSS脆弱性』,サイト管理者は注意を」---専門家が警告) のように,自ら増殖機能を持つような”高度な応用”も現れ始めている。さらに,タグ文字のエスケープ漏れを悪用して偽のログイン画面や個人情報入力画面を作り,ログインIDやパスワードといった個人情報を盗み出すフィッシング手口も現れてきている(参考:「XSS脆弱性は危険,Cookieを盗まれるだけでは済まない」専門家が注意喚起)。 いずれの場合も対策は同じ。原因がHTMLエンコードの漏れなのだから,すべての項目についてHTMLエンコードすることが正しい対応である。この場合の注意は次の通り。細かいことをいちいち考えずに,可変となる変数や式などの表示に関してはすべからくHTMLエンコードすべしというのが原則である。表1に,変換すべきメタ文字と変換後の文字列を示す。
表1 HTMLのエスケープ処理
アプリケーションの要件から見てエンコードが不要なフィールドまでHTMLエンコードするのは無駄に思えるかもしれないが,そうではない。HTMLエンコードに要する労力はわずかなものだし,すべての項目をエンコードすることによりチェックなどが容易になる。すべてをエンコードすると決めたほうが簡明でミスが少なくなるわけだ。逆に,ある部分はエンコードし,別の部分はエンコードしないという状態になると,かえって煩わしい。このため,Webアプリケーションを開発する際には,フレームワークなどに自動エンコードの機能を組み込むことが望ましい。 このように,クロスサイト・スクリプティング対策の原則は単純そのものであり,難しいところは何もない。しかし実際には,多くのWebアプリケーション開発者に「HTMLエンコードの神話」が根付いており,このことが正しい対策の普及を遅らせているように思う。具体的には, といったものである。
【神話1】HiddenフィールドのValue属性などはエンコードする必要がない
注2)例えばFirefoxのアドオン・ツールには,Hiddenフィールドの値を変更するための便利なツールがある。
【神話2】クォート文字はエンコードする必要がない その理由としては, といったことが挙げられる。文字化けを利用したクロスサイト・スクリプティングとは次のようなものである。まず,次のような簡単な入力フォームのCGI(common gateway interface)断片を想定する(言語はPerlを想定)。
この例で,パラメータ$v1と$p1にそれぞれ,
という値をセットしてみる。すると,写真1のような画面が表示され,テキストボックスにマウス・カーソルがかかると,自動的にJavaScriptが実行される。写真はFirefoxで示したが,Internet Explorer(IE)やOperaでも同様の動作を確認している。また,文字コードはシフトJISがもっとも発生しやすいが,IEの場合,EUCでも同様の動作となった。 なぜこのような現象が発生するのか。この例では,0x81というデータはシフトJISコードの1バイト目のグループに属するため,後続のダブルクォート「"」がシフトJISコードの2バイト目と解釈されている。このため,Value属性が「閉じられない状態」のままになり,表示項目中の「onmouseover」という文字列が,onmouseoverイベント・ハンドラと解釈され,JavaScriptを実行してしまう。この際,変数$p1のダブルクォート「"」がエスケープされていれば,このような事態は避けられる。 この問題が発生する根本原因は何か?一つには,0x81という「単体では不正な文字」をそのまま表示したアプリケーション側の問題と言える。また,0x81とダブルクォート(0x22)の組み合わせはシフトJISとしてもEUCとしても該当文字はない注4)ことを考えると,「あり得ない文字」の取り扱いに関するブラウザの問題とも言える。しかし,このような問題が現実に発生し得ること,クォート文字のHTMLエンコードにより予防が可能であることなどから,「どんな場合でもクォート文字をエンコードする」というルールにしておくのが予防的プログラミングとして安全である。 注4)後続文字がシングルクォート「'」(0x27)の場合も同様である。
【神話3】Value属性値にHTMLエンコードすると,アプリケーション側でデコード処理が必要になる なお,ブログやSNSなど最近のWeb 2.0的なアプリケーションの普及により,テキスト入力フィールド内でタグ文字(「<」や「>」)を入力する機会が増えてきているが,そのような場合にこそ,Value属性値のエンコード処理は重要である。そうしなければ,タグ文字類が正確に表示されないケースがあるからである。
【神話4】二重にエンコードするのが心配だ
【神話5】出力よりも入力の方が対応個所が少なくて楽だ
【神話6】HTMLエンコードだけではクロスサイト・スクリプティングは完全には防御できない 連載新着連載目次へ >>
|