Hatena::ブログ(Diary)

hoshikuzu | star_dust の書斎 このページをアンテナに追加 RSSフィード Twitter

hoshikuzu|star_dustの日記について

書く内容の方針とかはフラフラしているのです。あまり考えていないかも知れません。面白いなぁと思うこと、大事なことだなぁと思うことを書いています。あんまり悲しいことは書かない主義。

 | 

2009-11-17 Firefox 2.0.0.20 におけるinnerHTMLの不備

Firefox 2.0.0.20 におけるinnerHTMLの不備 Firefox 2.0.0.20 におけるinnerHTMLの不備を含むブックマーク Firefox 2.0.0.20 におけるinnerHTMLの不備のブックマークコメント

次のようなコードをウェブアプリケーションで取り扱い、onclick属性で実現したいとします。

alert("ユーザが出力する文字")

次のような条件を考えて見ましょう。ユーザは、"を与えました。ですので、以下を考えたいわけです。

alert(""")

ここで、以下を参考に、JavaScript文字列内に、通説によるJavaScriptとしてエスケープすべき文字がみあたらないことに留意してください。

1. 「\」を「\\」に置換する
2. 「"」を「\"」に置換する
3. 「'」を「\'」に置換する
4. 「/」を「\/」に置換する
5. 「<」を「\x3c」に置換する
6. 「>」を「\x3e」に置換する
7. 「0x0D(CR)」を「\r」に置換する
8. 「0x0A(LF)」を「\n」に置換する

Re: JavaScript内(文字列)にデータを出力する場合の適切なエスケープ手順::Sea Surfers ML

そこで、HTML4.01で普通に書くならば、XSS対策として、HTMLレベルでの文字参照でのエスケープをほどこしてやることにより、ウェブアプリケーションは以下の断片を出力することが考えられます。JavaScriptレベルでのエスケープは不要と考えられるからです。

onclick="alert(&quot;&amp;quot;&quot;)"

この断片をimg要素の属性として付加したものをイメージAとします。イメージAを上位ノードのdiv要素のinnerHTMLとしてコピーし、HTML内側の他のdiv要素のinnerHTMLで貼り付けることを考えてみます。貼り付けられたものをイメージBと呼ぶこととします。サンプルHTMLを以下に掲げました。


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">

<html lang="JA">
<head>
  <meta http-equiv="Content-Script-Type" content="text/javascript">
  <meta http-equiv="Content-type" content="text/html; charset=utf-8">
  <meta http-equiv="Content-Style-Type" content="text/css">
  <style type="text/css" media="screen">
  <!-- 
  body { background-color: #000; font: 16px Helvetica, Arial; color: #fff; }
  -->
  </style>

  <title>Sandbox</title>
</head>

<body>
  <div id="i01">
    <img src="http://mozilla.jp/img/tignish/video/play.png"
         alt="dummy image"
         onclick="alert(&quot;&amp;quot;&quot;)">
  </div>
  <div id="i02">
    dummy string
  </div>

  <script type="text/javascript">
  <!--
  var q1 = document.getElementById("i01");
  var q2 = document.getElementById("i02");

  q2.innerHTML = q1.innerHTML;   //これが問題のイメージのinnerHTMLによるコピーです。

  alert(q1.childNodes[1].attributes.getNamedItem('onclick').nodeValue); //テスト1
  alert(q2.childNodes[1].attributes.getNamedItem('onclick').nodeValue); //テスト2
  // -->
  </script>
</body>
</html>

上のサンプルで、テスト1、テスト2の場所に、コピー元とコピー先のonclickアトリビュートの内容をalertしています。Firefox 2.0.0.20 で上のHTMLを開きますと、テスト1のalert結果は以下のようになります。

alert("&quot;")

これは期待通りです。ですけれど、テスト2のalert結果は次のようになります。

alert(""")

これは期待したものではありません。実行するとJavaScriptレベルでエラーになってしまいます。実際、上のサンプルHTMLでは、コピー元とコピー先の2個の画像が表示されますが、おのおの、マウスでクリックしてやると、イメージAではきちんと実行されますが、イメージBでは、エラーになってしまいます。

以上は、単にエラーになった、ということを意味していません。上記の性質を使用することによって、ブラウザサイドでのXSSを発動させることが可能なケースが出てくるからです。JavaScriptの文字列の中で適切な文字参照を使うことにより、innerHTMLでのコピー先でJavaScriptインジェクションが可能になってしまいます。たとえば、上の例で考えた&quot;の代わりに以下のようなものが考えられます。

&quot;);alert(document.URL);//

なお、Firefox 2 の最後のリリース(2008/12/18)のFirefox 2.0.0.20 までには上の弱点がありますが、Firefox 3 シリーズ以後には見受けられないようです。以前ご紹介したOpera 9.27 (8841) におけるinnerHTML取得時の引用符解釈の不備と同様に、頭の片隅にいれておくことが必要だと思われます。

※2009/2/27に[これはひどい]IEの引用符の解釈というhasegawayosukeさんによる記事が出ましたが、もう少し早いタイミングであれば、OperaやFirefoxでの類似バグが存在していたこととなります。ちなみに、Operaの方が先に修正されていたのですね。(;-p)

masamasa 2009/11/17 17:45 たぶん https://bugzilla.mozilla.org/show_bug.cgi?id=392511 だと思います。Firefox 3がβ版だった頃に直ったようです。

hoshikuzuhoshikuzu 2009/11/17 18:36 テストケースはこれですね。 
https://bug392511.bugzilla.mozilla.org/attachment.cgi?id=277016
2007-09-14 にはパッチのアイデアが出来上がっていたのに、2008/12/18時点のFirefox2で...というのが不思議といえば不思議です。

hoshikuzuhoshikuzu 2009/11/18 11:41 Bug 392511 の表題はinnerHTML getter fails ... となっていますけれど、getterでなくてsetterが壊れていたのではないかと思ったりします。 よくわかりません。

トラックバック - http://d.hatena.ne.jp/hoshikuzu/20091117
 | 
最近のコメント