第1回 Ajaxとクロスサイトスクリプティング|gihyo.jp

JVNの常連である福森さんの記事。
1ページ目の最終段が


このように不正なスクリプトを入力されたとしても,それをそのまま出力しないでエスケープ処理を行ってから出力することが,クロスサイトスクリプティング対策になります。
で終ってますが、ここで終ってしまうよりは、せっかくAjaxしてるので createTextNode するような安全な実装を示して欲しいなと思いました。(2007/06/28追記。このコードは脆弱です!)

      if (req.readyState == 4) {
        var t = document.createTextNode( req.responseText );
        document.body.appendChild( t );
        // document.write(req.responseText); document.write は使わない
      }


(2007/06/28追記)
↑これじゃ確かに[脆弱性][XSS][bad]ですね。
上のコードは、「エスケープ処理を行ってから出力」を、document.write( escapeHTML( req.responseText ) ) みたいなイメージで捉えて、それならエスケープせずに JavaScript から DOM ベースでアクセスしたほうがいいじゃん、と思って書いたのですが、それではやっぱりだめすぎです。
サーバ側でエスケープせずに、レンダリングする JavaScript でHTMLエスケープや createTextNode していると、Webアプリケーションとして動いている間はいいのですが、Ajaxのデータ(この例ではcontents.cgiのレスポンス)に直接IEでアクセスした場合に、例えレスポンスが text/plain であっても XSSしてしまいます。なので、こういった場合はサーバ側での出力時のエスケープが必須です…という話が2ページ目に続くわけですね。
うーん…。レスポンスを application/xml で返し、responseXML で受け取っている場合には、IEで直接アクセスしてもHTMLと解釈されることはないはずなので、上のような JavaScript 側での対策が生きてくると思います。


(2007/06/29追記)
徳丸さんの「ockeghem(徳丸浩)の日記 - 「第1回 Ajaxとクロスサイトスクリプティング」を読んで」。福森さんの記事を読んだときになんとなくモヤモヤした感じを受けた理由がようやくわかりました。「なんとなくモヤモヤ」などと、漠然としか判りにくさを把握できてない時点で読解力なさすぎ…。