水無月ばけらのえび日記

bakera.jp > 水無月ばけらのえび日記 > jQueryの落とし穴

jQueryの落とし穴

2011年6月24日(金曜日)

jQueryの落とし穴

公開: 2011年7月3日19時35分頃

jQueryにおけるXSSを引き起こしやすい問題について (subtech.g.hatena.ne.jp)」。これは非常に興味深いお話ですね。

jQuery (jquery.com)はJavaScriptのライブラリですが、最近ではもうほとんどのサイトで使われていると言っても過言ではないくらい使われています。これは非常に便利で、面倒なDOM操作をとても簡単に書くことができます。たとえばこんな感じです。

$(function(){
    $('#main-contents>div').append($('<p>こんにちは</p>'))
});

上記のようなコードは良くあるのですが、よく見ると、$() は渡されたものの種類によって全く違う動作をしている事が分かります。

この他に、DOMのノードを渡すとjQueryオブジェクトに変換する機能もあります。

ポイントは文字列を渡したときの動作が2種類あることで、しかも、それぞれが全く違う動作になります。そのため、既存のノードを選択しようと思っていたのに要素が作られてしまうということが起こり得ます。

jQuery1.6.1のソースコードを見ると、以下のような正規表現にマッチした場合に要素作成になるようです。

quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/

先頭のほうに [^<]* があるのがポイントで、開始タグの前に任意の文字列が存在していても良いことになっています。'#foo-bar<tag>' のような文字列はこれにマッチしますので、要素が作成されることになります。

script要素が作られても、それがDOMツリーに挿入されなければ問題ない……と思うかもしれませんが、onerrorイベント付きのimg要素を作らせるような技があり、挿入されなくてもスクリプトを実行させることができてしまいます。これがXSSの原因になり得る、というのが今回のお話です。

$() が万能というのはjQueryの設計思想なのだと思いますが、型が同じ (文字列型の) 引数を渡しているのに挙動が全く違うというのは、予期せぬところで問題を引き起こしやすいだろうとは思います。

関連する話題: Web / セキュリティ / JavaScript

最近の日記

関わった本など