<前の日記(2005-12-23) 次の日記(2005-12-27)> 最新

おおいわのこめんと (2005-12-26)


2005-12-26

[Security] 文字コードとXSS

(書きかけ)

例によってセキュリティホールmemoより。厄介ですねぇ……。

  • キチンと全文書に文字コード指定をしておく
  • マイナーな文字コードで送信するときは、対応環境と影響を考えておく。 不安なら ASCII 完全上位互換の文字コード (ASCII の有効バイトは常に ASCII と同じ意味を持つ EUC-JP、UTF-8 など) を使う。
  • cross-site injection で META が埋め込めるとかは論外。

位は比較的簡単だし、やっておかないといけないかな。

で、ちょっと気になっているのとしては、とりあえず、UTF-7 はやばやばなのは明らかとして、 ISO-2022-* への派生している議論はちょっとずれている気がしている。 とりあえず、 Bugzilla.jp の 4868: ASCIIと互換性のない文字コードはユーザーの指定で選択可能にすべきでない は、ちょっと違うかなぁ……。 ユーザによる強制文字コード指定で脆弱性が生じるケースとしては例えば 星屑さんの日記に 示されているわけだが、これは「ISO-2022-JP を SJIS で解釈すると危険」という話なので、 この Bugzilla で提案される対策をしても意味がない(順序が逆)。 一般論としてはこの手の危険性をメニューからの削除で対策するなら、 EUC-JP とか Shift_JIS とか ASCII とかも禁止しないと対策にならないが、 それはさすがにちょっと的を外してしまう。

ASCII のバイト列を ISO-2022-* でうかつに解釈すると危険なケースというのは、 <ESC(Bscript> みたいなケースなのだが、これってもともと ASCII で安全か? と言われると、 未エスケープな文字が残っている時点でそもそも微妙……。 ISO-2022-* はある意味で ASCII 上位互換になっていて、主な問題は 「ASCII の特殊文字が文脈によっては特殊文字として扱われない」ということと、 上記のような元々微妙なバイト列がシーケンス消滅によって脆弱になるケースなので、 UTF-7の「ASCII の非特殊文字が文脈によっては特殊文字として扱われる」*1ケースとは取るべき対策が異なるのではないか。

ASCII や ISO-8859-1 の表示可能文字+単純な制御記号 (CR, LF, SPC, HT, FF) だけで構成された 未エスケープ単独文字を含まない正当な HTML 文書で、ISO-2022-* で評価すると危険な例は ちょっとまだ思いついていない。その点からも、とりあえず ASCII / ISO-8859-1 などで ESC(そもそも非表示文字だし)をキチンと処理しておいた方がいいのは確かなようで。 これをやっておかないとちょっと嫌らしい例は作れる。("ESC $ B" で必要な閉じ記号だけを隠してしまうとか)。 尤もそれを言い出すと、EUC-JP とか Shift_JIS とかでも、 解釈器の作りによっては不完全なコードで 1バイト食い潰すのは可能だったりするので、 微妙な場合を生じうる。 もうちょっと正しい言い方をすれば、「文字コード指定をしたときに、 想定されるコード体系での正しいコードでないバイト列を出力してはいけない」、 「ASCII/ISO-8859-1 強制指定をしない場合は、少なくとも全ての ASCII 上位互換エンコーディングにおいて 特殊な意味を持たないコード (表示可能文字+一部の安全な制御文字) だけを出力しなければならない」になるだろうか。

この「異常入力」周りは、いずれちゃんと実験してみないといけないなぁ。時間がいくらあっても足りない。

ちなみに、IE で ISO-2022-JP がメニューに現れないのは、 危険だからではなくて、むしろ自動判定で完璧に判定される (他の ASCII 上位互換文字コードと曖昧なケースは ASCII 文字だけからなる文書の時だけ) からではないかと思うのだが。

尤も、EUC-JP のように完全に ASCII と独立した部分だけに拡張文字を持っている文字コードは、 確かに安全性は高い。どちらももともとそういう用途(ファイルシステムへの適応など)を十分に想定して 作られているから当然なのだが。そういう意味では、無理に CGI の出力を ISO-2022-JP にするよりは、 charset をつけて EUC-JP にしておくのは正しい気がしている。UTF-8 については、仕様上は安全なのだが、 例の「冗長な多バイトエンコード」の問題について個々の実装に注意が必要か。 Shift_JIS は、HTML に関しては偶々特殊文字が 0x3f 以下に集中しているので、とりあえずは大丈夫かな。 CSS とかだと \ (0x5f) が嫌な感じかも。

あと、場当たり的で嫌ではあるが、ISO-2022-JP については、ASCII に変換(あるいは誤解釈)したときに 2文字以上の意味のあるタグに化けることを防ぐ方法は 実は存在したり (危険な文字の直後に ESC $ B を挟んでしまう) するのだが……。

この項、数日中にもう一回まとめます。

もうちょっと整理してみる。

とりあえず、本当は文字コードの全組み合わせに対してマトリクスを作るべきなのですが、 実際は ISO-8859-1 との二者関係の組み合わせにほぼ帰着できるので、とりあえずそれで考えてみます。

ISO-8859-1 の8ビットのバイト列を入力として、 別の文字コードで解釈したときに、次の可能性が考えられます。

  1. ASCII 部分の解釈が完全に一致し、GR 部分の文字の切り方も一致する
    • (ASCII)
    • ISO-8859-*
  2. ASCII 部分の解釈が完全に一致するが、GR の列は一部無効な組合わせになることもある
    • EUC-JP
    • UTF-8 (注)
  3. ISO-8859-1 可読範囲外のバイトの影響で、ASCII の文字だったバイトが、 ASCII 文字集合外の別の文字に解釈されることがある
    1. ほぼ全ての ASCII 文字が該当
      • ISO-2022-JP
  4. ISO-8859-1 可読範囲内の文字列が、ASCII 文字集合外の別の文字に解釈されることがある
    1. アルファベットと一部の記号に限る
      • Shift_JIS
    2. ほぼ全ての ASCII 文字が該当
      • UTF-1
      • HZ
  5. 何らかのバイト列が、元と違う ASCII の文字に解釈される
    • UTF-7

まず、1. や 2. のケースでは、ほとんど問題は生じません。2. のケースでは、 例えば < 0xa1 s c r i p t > のような列があったとき、 0xa1 を無効な文字として単純に除去してしまうと、ちょっと嫌な感じになりますが……。 UTF-8 については、「例のバグの問題」がありますが、まぁとっくに直ってると思いたいところです。

次に、3. や 4. のケースでは、次の3つの問題があります。 まず、上記の設定と逆に当該の文字集合で書かれた文書を誤って ASCII で解釈した際に、 本来無かった特別な意味を持ってしまう可能性があります。 先ほどの星屑さんの日記の例がそれで、 本来の ISO-2022-JP では特殊な意味がなかったバイト列が、ASCII では無効文字 ESC と多少の正当な文字と、 script タグに解釈されてしまいます。 尤も、4. の中でも Shift_JIS の2バイト文字には、HTML の特殊文字 " < > & に相当するバイトが含まれないので、 危険性は低減されます (但し \ に注意)。

また、タグ要素中にそのようなシーケンスが現れると、要素終了の " や > などが 吸収され、タグが閉じなくなる可能性があります。3. では非可読な文字が必ず存在しますので、 そのような文字をエスケープしてしまえば済みますし、Shift_JIS や UTF-1 でも 必ず GR のコードが含まれますが、HZ は嫌らしいところです。

また、ISO-2022-JP などでは、一部のバイト列が ISO-2022-JP では0文字に縮退することがあるため、上で挙げたような例 (<ESC(Bscript>)のように、ASCII で無効だった文字列が ISO-2022-JP で有効な ASCII 相当文字の列として解釈される可能性があります。 ISO-2022-JP の場合、このようなシーケンスは必ず特殊文字 ESC を含みますし、HZ などでは 必ずしもそうではありません。特に HZ では ASCII 可読文字の列 ~{~} が縮退する 可能性がありますので、選択的なタグ除去などをしている場合には注意が必要でしょう。 UTF-1 では (有効なバイト列では) この問題はないはずです。また、無効バイト列の問題は 2. と同様です。

最後に、5. のケースは、今回の問題にありましたが、かなり対処が困難です。 自動判別されてしまうと、完全にASCII可読文字が別の解釈を持ってしまうので始末が悪いです。 この場合、「ブラウザはこのような文字集合を自動判定の候補とすべきでない」といえるでしょう。

*1 さすがに ISO-2022-JP において、X0208 の < がタグ開始記号と同一視されるって実装は聞いたことがない。

[TrackBack URL: http://www.oiwa.jp/~yutaka/tdiary/trackback.rb/20051226 (note: TrackBacks are moderated: spams will not be shown.) ]

大岩 寛 (おおいわ ゆたか) <yutaka@oiwa.jp.nospam ... remove .nospam> .

Copyright © 2005-2014 Yutaka OIWA. All rights reserved.
Posted comments and trackbacks are copyrighted by their respective posters.

記事の内容について (Disclaimer / Terms and Conditions)