連載
» 2006年09月23日 00時00分 公開

星野君のWebアプリほのぼの改造計画(10):マルチバイトの落とし穴 (2/3)

[杉山俊春, Illustrated by はるぷ,三井物産セキュアディレクション株式会社]

「%82」のなぞ

赤坂さん 「さて、じゃあ答え♪」

 そういうと、赤坂さんはキーボードをたたき、何やら入力した。

星野君 「あ!!」

 絶対安全じゃないかと思われたソースコードだったのだが、見事にスクリプトが動作し、クロスサイトスクリプティングが成功してしまっていた。

星野君 「ええ!?何でスクリプト動くんですか??」

 星野君は、表示されたページのソースを見てみたが、よく分からない。何やらおかしな文字が交ざってはいるが……。

<form>
テキスト1: <input type=text name=text1 value="><br>
テキスト2: <input type=text name=text2 value=" onmouseover=alert('xss')><br>
<input type=submit value="送信">
</form>
(1)ページのソースをメモ帳で開いたところ

赤坂さん 「ソース見てもたぶん分かんないと思うよ。ここ見ないと」

星野君 「??」

 そういうと赤坂さんはアドレスバーの部分を指差した。そこには以下のような文字列が記述されていた。

http://www.example.com/break_quote.php?text1=%82&text2=%20onmouseover=alert('xss')%20%82


アドレスバーを指さす赤坂さん

星野君 「いや……、ここ見ても分かんないですけど……」

赤坂さん 「えー。っていっても、私も最初よく分かんなかったけどね。これは〜……」

 一見安全そうに見えるソースコードであったが、そこには意外な落とし穴が存在していた。赤坂さんの入力には、「%82」という文字列が含まれている。これは、SJISのマルチバイト文字の1バイト目をURLエンコードしたものである【注1】。

【注1】
「%82」は全角日本語の「あ」(%82%A0)や、「い」(%82%A2)などの1バイト目。「%20」は半角スペース。


 多くのWebアプリケーションでは、入力されたマルチバイト文字列が完全なものであるかをチェックしないため、1バイトのみ入力してもそのまま処理する作りになっている。「%82」はURLでコードした場合、メモ帳などでは半角スペースと同じ見た目になっているが、実際には以下のような「0x82」の形になっている。

<form>
テキスト1: <input type=text name=text1 value="[マルチバイト文字の1バイト目(0x82)]"><br>
テキスト2: <input type=text name=text2 value="onmouseover=alert('xss') [マルチバイト文字の1バイト目(0x82)]"><br>
<input type=submit value="送信">
</form>
(2)実際のページのソース

 さらに、このソースに対してWebブラウザは以下のような解釈をする。

Webブラウザ(Internet Explorer、Firefox、Opera)の解釈 Webブラウザ(Internet Explorer、Firefox、Opera)の解釈(画像をクリックすると拡大します)

 Webブラウザでは、マルチバイトの1バイト目とその後ろのダブルクオーテーションを合わせてマルチバイトの1文字として扱ってしまう。そのため、直近のダブルクオーテーションまでが属性値として認識されてしまい、本来記述できないはずの属性(ここでは「onmouseover」)が記述可能になる。その属性値を利用することで、スクリプトが自由に記述できるのだ。

【参考リンク】
Bypassing script filters with variable-width encodings

http://applesoup.googlepages.com/bypass_filter.txt


星野君 「うわ。これなんか危なくないすか?」

赤坂さん 「でしょー。これ教えてもらったときはちょっとびっくりしたもん」

星野君 「これ使ったら、いろんなアプリでクロスサイトスクリプティングが動いちゃうんじゃないですか?」

赤坂さん 「まあ、実際にはスクリプトが動作するところまでいかないパターンが多いんだけどね」

 (1)で示したソースではスクリプトが動作してしまったが、ほかの属性値がダブルクオーテーションでくくられている場合は、Webブラウザの解釈が異なってくる。

Webブラウザ(Internet Explorer、Opera)の解釈(※Firefoxの場合は多少解釈が異なるがスクリプトは動作しない) Webブラウザ(Internet Explorer、Opera)の解釈(画像をクリックすると拡大します)(※Firefoxの場合は多少解釈が異なるがスクリプトは動作しない)

 マルチバイトの1バイト目(0x82)によって壊れてしまったダブルクオーテーションは、直近のダブルクオーテーション(この場合は、type属性の開始部分)によって終端される。しかし、属性値が終端した直後が不正であると【注2】ダブルクオーテーションが含まれても無視され、以降の属性値が正しく扱われる。この結果、タグは壊れてしまうものの、スクリプトが動作するまでには至らない。

【注2】
属性値の直後に半角スペースがなく、[属性名=属性値]の形式や、ダブルクオーテーションで囲まれていない「>」を含む文字列以外の場合、不正となり無視される。

・無視される例(赤字部分が無視される)
<input type="text"text" name="name" value="value">

・無視されない例
<input type="text"name="name"value="value">
 :正しいタグとして認識される
<input type="text"
text>name="name"value="value">
 :赤字部分は無視され、青字部分がタグとして認識される

星野君 「……うーん。なんかよく分かんなくなってきました」

赤坂さん 「実際にいろいろ検証してみると分かりやすいと思うよ」

Copyright© 2018 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。