「%82」のなぞ
赤坂さん 「さて、じゃあ答え♪」
そういうと、赤坂さんはキーボードをたたき、何やら入力した。
星野君 「あ!!」
絶対安全じゃないかと思われたソースコードだったのだが、見事にスクリプトが動作し、クロスサイトスクリプティングが成功してしまっていた。
星野君 「ええ!?何でスクリプト動くんですか??」
星野君は、表示されたページのソースを見てみたが、よく分からない。何やらおかしな文字が交ざってはいるが……。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
赤坂さん 「ソース見てもたぶん分かんないと思うよ。ここ見ないと」
星野君 「??」
そういうと赤坂さんはアドレスバーの部分を指差した。そこには以下のような文字列が記述されていた。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
星野君 「いや……、ここ見ても分かんないですけど……」
赤坂さん 「えー。っていっても、私も最初よく分かんなかったけどね。これは〜……」
一見安全そうに見えるソースコードであったが、そこには意外な落とし穴が存在していた。赤坂さんの入力には、「%82」という文字列が含まれている。これは、SJISのマルチバイト文字の1バイト目をURLエンコードしたものである【注1】。
【注1】
「%82」は全角日本語の「あ」(%82%A0)や、「い」(%82%A2)などの1バイト目。「%20」は半角スペース。
多くのWebアプリケーションでは、入力されたマルチバイト文字列が完全なものであるかをチェックしないため、1バイトのみ入力してもそのまま処理する作りになっている。「%82」はURLでコードした場合、メモ帳などでは半角スペースと同じ見た目になっているが、実際には以下のような「0x82」の形になっている。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
さらに、このソースに対してWebブラウザは以下のような解釈をする。
Webブラウザでは、マルチバイトの1バイト目とその後ろのダブルクオーテーションを合わせてマルチバイトの1文字として扱ってしまう。そのため、直近のダブルクオーテーションまでが属性値として認識されてしまい、本来記述できないはずの属性(ここでは「onmouseover」)が記述可能になる。その属性値を利用することで、スクリプトが自由に記述できるのだ。
【参考リンク】
Bypassing script filters with variable-width encodings
http://applesoup.googlepages.com/bypass_filter.txt
星野君 「うわ。これなんか危なくないすか?」
赤坂さん 「でしょー。これ教えてもらったときはちょっとびっくりしたもん」
星野君 「これ使ったら、いろんなアプリでクロスサイトスクリプティングが動いちゃうんじゃないですか?」
赤坂さん 「まあ、実際にはスクリプトが動作するところまでいかないパターンが多いんだけどね」
(1)で示したソースではスクリプトが動作してしまったが、ほかの属性値がダブルクオーテーションでくくられている場合は、Webブラウザの解釈が異なってくる。
マルチバイトの1バイト目(0x82)によって壊れてしまったダブルクオーテーションは、直近のダブルクオーテーション(この場合は、type属性の開始部分)によって終端される。しかし、属性値が終端した直後が不正であると【注2】ダブルクオーテーションが含まれても無視され、以降の属性値が正しく扱われる。この結果、タグは壊れてしまうものの、スクリプトが動作するまでには至らない。
*** 一部省略されたコンテンツがあります。PC版でご覧ください。 ***
星野君 「……うーん。なんかよく分かんなくなってきました」
赤坂さん 「実際にいろいろ検証してみると分かりやすいと思うよ」
Copyright © ITmedia, Inc. All Rights Reserved.