そろそろ UTF-7 について一言いっとくか

UTF-7を利用したXSSは、charset が指定されていない場合に発生すると考えられていますが、少なくとも Internet Explorer においては、これは大きな間違いです。正しくは、Internet Explorer が認識できる charset が指定されていない場合であり、charsetが付加されていても、IEが認識できない文字エンコーディング名である場合にはXSSが発生します。
例えば、次のような HTML は(HTTPレスポンスヘッダで charset が明示されていない場合)IEが文字エンコーディング名を正しく認識できないため、その内容からUTF-7と解釈されるためにスクリプトが動作します。"utf8"という表記はUTF-8の慣用的な表現ではありますが、ハイフンが抜けており正しい表記ではありません。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
</head>
<body>
+ADw-script+AD4-alert(document.location)+ADsAPA-/script+AD4-
</body>
</html>

IE が正しく判別できる文字エンコーディング名の一覧は、レジストリの HKCR\MIME\Database\charset 以下に定義されています。"utf8"のような、ここに列挙されていない文字エンコーディング名は、IEでは正しいエンコーディング名を認識できないため、Webアプリケーションがそのような文字エンコーディング名を送出している場合には、攻撃者はCVE-2007-1114などと組み合わせることにより、XSSを発生させることが可能となります。

例示した"utf8"以外に、国内のWebアプリケーションにありがちな、IEが認識できない文字エンコーディング名としては以下のようなものがあります。

jis
ISO-2022-JPの慣用的な表現
MS932 / CP932 / CP942C
Java上の Shift_JIS の類似エンコーディング
Windows-31J
Windowsで使用されているコードページ932のIANA正式登録名。これが認識できないのはどう考えてもIEが悪いと思います。

Webアプリケーション上で文字エンコーディングをハードコーディングしている場合だけでなく

[]http://example.com/?q=abcd&[]charset=euc-jp
のように、パラメータにより外部から文字エンコーディングを指定可能なものも見かけます。指定された文字エンコーディングに従いパラメータを解釈するだけでなく、出力も指定された文字エンコーディングに従って変換するようなものです。こういった類のWebアプリケーションにおいて前述した CP932 などの文字エンコーディング名を許容している場合には、XSSが発生します。
[]http://example.com/?q=%2BADw-script%2BAD4-alert%28document.location%29ADsAPA-/script%2BAD4-&[]charset=CP932
エラーページなども含め、あらゆるコンテンツでは文字エンコーディング名として Shift_JISUTF-8 といった問題のない名称を使用するように心がけましょう。

よいお知らせ

上記の内容について、Microsoftに対して Internet Explorer の仕様改善の要望として提出したところ*1脆弱性として届け出なおして欲しいとの返答を得ました。そこで、改めて脆弱性として届け出たところ、次のような回答を頂きました(要旨抜粋)。

本事象につきましては、既に公開されている内容と同一であり、弊社では Internet Explorer脆弱性と判断しております。
弊社では、本事象の対応が必要であると認識しており、現在、対応策を検討中でございます。

将来的には、上記のような状況でのXSSの発生が減る方向にIEが修正される、ということです。まさか、MicrosoftIEのこのような挙動に対して脆弱性として判断するとは思っていなかったので実に意外でした。

2007年07月18日追記

セキュリティホール memoにて「IE はそれを UTF-7 と誤認する場合があり」と書かれていますが、IE7においてはCVE-2007-1114を利用することで、ほぼ確実にUTF-7と誤認させること、すなわちXSSを発生させることができます。なので「場合があり」というほどぬるい状況ではなく、この方法によるXSSを防ぐためには、Webアプリケーション側は必ずIEが識別可能な charset を送出してやらなければなりません。

*1:Microsoftの言う「セキュリティの脆弱性」の定義には当てはまらないと考え、仕様改善の要望とした。