Home > Latest topics

Latest topics > JavaScriptのスタックトレース

宣伝1。日経LinuxにてLinuxの基礎?を紹介する漫画「シス管系女子」を連載させていただいています。 以下の特設サイトにて、単行本まんがでわかるLinux シス管系女子の試し読みが可能! シス管系女子って何!? - 「シス管系女子」特設サイト

宣伝2。Firefox Hacks Rebooted発売中。本書の1/3を使って、再起動不要なアドオンの作り方のテクニックや非同期処理の効率のいい書き方などを解説しています。既刊のFirefox 3 Hacks拡張機能開発チュートリアルと併せてどうぞ。

Firefox Hacks Rebooted ―Mozillaテクノロジ徹底活用テクニック
浅井 智也 池田 譲治 小山田 昌史 五味渕 大賀 下田 洋志 寺田 真 松澤 太郎
オライリージャパン

JavaScriptのスタックトレース - Jul 26, 2010

先日のブラウザー勉強会吾郷さんにお会いした際に、JavaScriptには言語の仕様として「例外がどこから投げられたのか」を知る為の仕組みが無いので独自のフレームワークを作る時に困ったという話を伺った。オレ標準JavaScript勉強会で何話せばいいか困ってた所だったので、それをネタに発表させてもらう事にした

改めてECMAScriptの仕様書を確認してみたけど、確かに3rd Editionと5th Editionでは、例外オブジェクトの機能としてはError.prototype.nameError.prototype.messageしか定義されていなかった(あとはconstructorとかtoString()とかその程度)。Wikipedia(英語の方)のECMAScriptの記事によるとECMAScript 3rd EditionはJavaScript 1.5とJScript 5.5の共通部分を抜き出す形で策定されたようで、実装してない方のIEに合わせてこうなったのか?とも思ったけど、調べてみたらJavaScript 1.5の頃はMozillaもError.prototype.stackはサポートしてなかった。それ以降にMozillaが独自に拡張した箇所ということのようだ。でも今回調べた限りではOperaもChromeもError.prototype.stackをサポートしていた(Operaの場合はこれに加えて、少しフォーマットが違うスタックトレースをError.prototype.stacktraceでも取得できる、ということをedvakfさんに教えていただいた)。メジャーなJavaScript実行環境でこれに対応してないのはIE(IE9PP3を含む)くらいのようだ……と思ったらSafari(Windows版)もサポートしていなかった。

吾郷さんのそれやUxUのようにデバッグを支援するためのフレームワークでは、スタックトレースは欠かせない要素だ。将来のECMAScriptの仕様に取り込まれてくれればいいのになあ、と思う。

勉強会ではせがわようすけさんに突っ込まれたけど、セキュリティのためにはなるべくこういう情報は出さない方がいいものらしい。しかし自分はスタックトレースの何がまずいのかがよく分かっていない。会場では「例えばスタックトレースでスクリプトのURLの中にセッションIDが含まれていたらセッションハイジャックされてしまう危険性がある」という例を教えていただいたけれども、それでもまだピンと来ていなかった。

さらにツッコミを受けたことで「なるほど、クロスドメインの制約を突破されてしまう」という事が問題なのだと分かった。ただ、実際にそれが問題になるケースってほんとにあるのかな? という疑問はまだ残っている。

分かりやすい話として、通常のXMLHttpRequestやiframeでは、別ドメインのドキュメントを読み込む事ができない・読み込んだとしてもその内容にスクリプトからアクセスすることはできない。

var iframe = document.createElement('iframe');
iframe.setAttribute('src', 'http://www.google.co.jp');
document.body.appendChild(iframe);
window.setTimeout(function() {
  try{
    alert(iframe.contentDocument.body);
  }
  catch(e){
    alert(e);
  }
}, 3000);

例えばこういうのは、Error: Permission denied for <http://piro.sakura.ne.jp> to get property HTMLDocument.body from <http://www.google.co.jp>.と言われてエラーになる。しかしスタックトレースにエラー行の詳細な情報が含まれていると、

try {
  document.write('<script type="text/javascript" src="http://www.google.co.jp/" async="false" defer="false"></script>');
}
catch(e) {
  var contentsFragment = e.stack;
}

とか

try {
  var script = document.createElement('script');
  script.setAttribute('type', 'text/javascript');
  script.setAttribute('src', 'http://www.google.co.jp/');
  script.setAttribute('async', 'false');
  script.setAttribute('defer', 'false');
  document.body.appendChild(script);
}
catch(e) {
  var contentsFragment = e.stack;
}

とか

// window.onerrorはECMAScriptの仕様にはない独自拡張
window.onerror = function(aMessage, aSource, aLineNumber) {
  // ここでaMessage, aSourceから情報を取れる可能性がある
}
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', 'http://www.google.co.jp/');
script.setAttribute('async', 'false');
script.setAttribute('defer', 'false');
document.body.appendChild(script);

という風にして、別ドメインのドキュメントの内容を部分的にとはいえ読み取れてしまう可能性がある、というわけだ。特に3番目のwindow.onerrorを使う例はMFSA 2010-47: エラーメッセージのスクリプトファイル名からのクロスサイトデータ漏えいで実際に脆弱性になっていたことが確認されていて、既に修正されている。

なお、実際に現行バージョンのFirefox・Opera・Chromeで試してみたところ、1番目・2番目のtry-catchを使った例ではそもそも例外を例外として(そもそも、エラーが発生したのかどうかすら)捕捉できなかったので、今の所問題にはならない。ただ、今は問題にならなくても、今後登場するJavaScriptの実装ではこういう場合でも情報を取れるようになっている可能性はあるので、将来的に脆弱性の原因になるかもしれないという警告は確かにアリだとは思う。という所までは何とか理解できた。

ブラウザのレベルでは、クロスドメインやクロスオリジンになる時だけは例外を出さないとか詳細な情報を出さないとか、そういう対応の仕方はあるだろうけれども、「ECMAScript」の仕様でそこに言及するのは変だろうなあ。というややこしい事情を勘案すると、もう丸ごと全部仕様からドロップしてしまえという判断になるんかなあ。

分類:Web技術 > JavaScript, , , 時刻:12:16 | Comments/Trackbacks (0) | Edit

Comments/Trackbacks

TrackBack ping me at


の末尾に2014年1月19日時点の日本の首相のファミリーネーム(ローマ字で回答)を繋げて下さい。例えば「noda」なら、「2010-07-26_stacktrace.trackbacknoda」です。これは機械的なトラックバックスパムを防止するための措置です。

Post a comment

writeback message: Ready to post a comment.

2014年1月19日時点の日本の首相のファミリーネーム(ひらがなで回答)

Powered by blosxom 2.0 + starter kit
Home

カテゴリ一覧

過去の記事

1999.2~2005.8

最近のつぶやき

オススメ

Mozilla Firefox ブラウザ無料ダウンロード