CHAPTER::タイトル Firefoxの 拡張機能と セキュリティ ---- Powered by 高橋メソッド in XUL [[EM:RETURNS:EM]] ---- この日のために パワーアップ (マジ) ---- CHAPTER::自己紹介 自己 紹介 ---- HEADER::自己紹介 下田洋志(Piro) 株式会社グッデイ チーフデザイナー ---- チーフデザイナー =ヒラデザイナー =デザイン系雑用係 ---- 元は Webサイト 制作を志向 ---- プログラミ ングは素人 ---- 外してる所が あったら容赦なく ツッコんで! ---- 宣伝 ---- オープンガイドブック OpenOffice.org 2.0 [[image src="openguidebook.png" width="410" height="450"]] 表紙・挿絵をやりました オープンソース繋がりでひとつヨロシク ---- CHAPTER::概要 HEADER:: 概要 ---- HEADER::概要 Firefoxの何が危険なのか ↓ 具体的にどんな危険があるのか ↓ どんな対策が施されているのか ---- 拡張機能の開発や 導入で穴を開けて しまわないための ---- 教訓にし て下さい ---- HEADER:: CHAPTER::前提 前提 ---- HEADER::前提 どんなアプリケーショ ンにもあり得る危険性 については述べません ---- あくまで Firefoxの特徴に 関する話題のみ (当たり前) ---- [[EM:扱わない話題の例:EM]] メモリオーバーフローとか 国際化ドメインに関する 脆弱性とか ---- HEADER:: CHAPTER::基本のおさらい 基本の おさらい ---- HEADER::基本のおさらい Firefox の構造 ---- Firefoxは [XML]関連技術と [JavaScript]と [CSS] でできている ---- Dynamic HTMLや Ajaxで作られた Webアプリケーション によく似ている ---- それだけでは [ファイルの保存] [バイナリ情報の処理] 等は不可能 ---- そこで XPCOM コンポー ネント ---- ローカルファイル へのアクセスなど 高度な機能を提供 するライブラリ ---- Firefoxを 複数プラット フォームで 動かすための コア技術 ---- JavaScriptからも XPCOM コンポーネント を呼び出せる ([XPConnect]) ---- つまり Firefox内部では JavaScriptで ローカルファイルへ アクセスしたり している ---- IEにおける [ActiveXコンポーネント] と似た働き ---- ぶっちゃけ JavaScriptで レジストリ破壊から 起動ドライブの フォーマットまで 何でもできる ---- だから セキュリティ 制限 ---- Webページ内の JavaScriptでは XPConnectは 利用できない ---- つまり ---- Webページ内の JavaScriptからは XPCOMを 呼び出せない ---- これが 基本原則 ---- HEADER:: CHAPTER::Firefoxの何が危険なのか/サンドボックス 本題 ---- HEADER::本題 Firefoxの 何が危険 なのか ---- HEADER::Firefoxの何が危険なのか XUL+CSS+ [JavaScript] という設計 に落とし穴 ---- JavaScriptという 実行可能な要素が サンドボックス 内外で共通して存在 ---- HEADER::JavaScriptがサンドボックス内外で共通 サンド ボックス って? ---- [[EM:サンドボックス(sandbox):EM]] 外部に危険な影響を与えないで スクリプトなどを動作させる ための、隔離された領域 (例:Java仮想マシン) ---- [[image src="sandbox1.png" width="963" height="622"]] FOOTER::サンドボックスのイメージ ---- FOOTER:: サンド ボックス の特徴 ---- サンドボックス の中では危険な 事はできない (セキュリティ制限) ---- 外側とメモリ空間が 切り離されている (こともある) ---- サンドボックス内で スクリプトなどが 暴れても致命的な ダメージは受けない ---- さらに ---- サンドボックス の中と外で構造が 大きく違えば ---- サンドボックス内の スクリプトが サンドボックス外で 暴れることは できない ---- 例: サンドボックス内 →JavaScript サンドボックス外 →ネイティブコード という構造なら ---- JavaScriptは サンドボックス外 では何もできない ---- [[image src="sandbox3.png" width="914" height="474"]] FOOTER::サンドボックスの中と外で環境が違うイメージ ---- FOOTER:: Firefoxの サンド ボックス ---- スクリプトを含んでいる リソースのURIで サンドボックスに 入れるかどうかが変わる ---- [[EM:chrome://...:EM]] だけ サンドボックス外 [[EM:http://...:EM]] [[EM:https://...:EM]] [[EM:file://...:EM]] など すべてサンドボックス内 ---- Firefoxは サンドボックス内 サンドボックス外も JavaScriptで動作 ---- WebページのJavaScript サンドボックス[内]で動作 セキュリティ制限[あり] Firefox内部のJavaScript サンドボックス[外]で動作 セキュリティ制限[なし] ---- サンドボックス の中と外で構造 がよく似ている ---- という ことは ---- サンドボックス内 のスクリプトを サンドボックス外 に ---- うっかり 持ち出したり したら ---- そのまま 動いて しまう ---- [[image src="sandbox2.png" width="987" height="607"]] FOOTER::危険なコードをサンドボックス外に出してしまったイメージ ---- FOOTER:: その逆もある (詳しくは後ほど) ---- 凄く 危険 ---- HEADER:: 今回のテーマ ---- HEADER::今回のテーマ Firefoxの セキュリティの 鍵 ---- HEADER::今回のテーマ サンドボックス 内外のスクリプトの 往来をいかにして 制限するか ---- CHAPTER::危険要素1:eval()関数 HEADER:: 危険要素 その1 ---- HEADER::危険要素1 eval() 関数 ---- HEADER::危険要素1:eval()関数 [[EM:eval('文字列'):EM]] 渡された文字列を現在の 実行コンテキストの権限で JavaScript文として そのまま評価・実行する ---- 危険 な例 ---- 読み込まれている Webページ内の イベントハンドラの 返り値を取得する場合 (古いタブブラウザ拡張) ---- 脆弱性 ---- Webページ内 に仕込まれた 悪意あるコードを 実行してしまう ---- [[PRE: gBrowser.addEventListener('click', function(event){ var win = _content; // content window var node = event.target; var returnValue = (function() { with(win){ with(node){ eval(node.getAttribute('onclick')); } } })(); alert(returnValue); }, true); :PRE]] [[PRE:node.getAttribute('onclick'):PRE]]に危険な コードが含まれていても構わず実行してしまう ---- 改善 ---- サンドボックス内の関数はサンドボックス内で実行するよう徹底 [[PRE: gBrowser.addEventListener('click', function(event){ var win = _content; // content window var node = event.target; win.done = false; win.node = node; node.originalHandler = node.onclick; node.onclick = function(event) { win.currentEvent = event; // サンドボックス内のsetTimeoutに文字列として渡した文は // サンドボックス内で実行される win.setTimeout( 'window.returnValue = win.node.originalHandler(window.currentEvent);'+ 'window.done = true;', 0 ); }; var timer = window.setInterval(function() { if (win.done) { window.clearInterval(timer); alert(win.returnValue); } }, 10); }, true); :PRE]] ---- HEADER:: CHAPTER::危険要素2:javascript: URL 危険要素 その2 ---- HEADER::危険要素2 javascript: URL ---- HEADER::危険要素2:javascript: URL [[EM:javascript:文字列:EM]] URIとして読み込むと 読み込み先フレームの 権限でJavaScript文として そのまま評価・実行する ---- サンドボックス内 ↓ [ドメイン]が[異なる] フレームに読み込むと エラーになる ---- サンドボックス外 ↓ [ドメイン]が[異なる] フレームに読み込んでも そのまま実行される ---- 危険 な例 ---- リンク先を Firefox内部の 関数で読み込む (サイドバーパネル) ---- [[image src="sidebar.png" width="557" height="440"]] FOOTER::サイドバーのフレームからブラウザのフレームへのリンク読み込み ---- FOOTER:: 脆弱性 ---- サイドバーに読み込 まれたページに仕込 まれた悪意あるコー ドを実行してしまう ---- サイドバーパネルとして表示されている Webページ内のリンクをブラウザで読み込む処理 [[PRE: target = linkNode.getAttribute("target"); if (fieldNormalClicks && (!target || target == "_content" || target == "_main")) { ... // リンク先がjavascript: URLの場合も特にチェックしない var url = getShortcutOrURI(linkNode.href, postData); ... // 現在表示されているページがabout:configなどの // Firefox内部の権限を持っている特別なページの場合、 // 読み込んだjavascript: URLを同じ権限で実行してしまう loadURI(url, null, postData.value); ... :PRE]] 任意のコードをFirefox内部の権限で実行してしまう ---- 改善 ---- Firefox 1.0.2以降での処理 [[PRE: target = linkNode.getAttribute("target"); if (fieldNormalClicks && (!target || target == "_content" || target == "_main")) { ... // リンク先がjavascript: URLの場合は問答無用で処理を中断 if (linkNode.href.substr(0, 11) === "javascript:") return true; ... var url = getShortcutOrURI(linkNode.href, postData); ... loadURI(url, null, postData.value); ... :PRE]] 読み込もうとしているのがjavascript: URLで ないかどうか事前にチェック ---- ドメインやフレームを 超えた読み込みを行う 時は、読み込むURIを 厳しくチェックする ---- HEADER:: CHAPTER::危険要素3:サンドボックスの越境 危険要素 その3 ---- HEADER::危険要素3 サンドボックスの 内外をまたいでの 関数の実行 ---- HEADER::危険要素3:サンドボックスの内外をまたいでの関数の実行 現在の実行 コンテキストの権限 と [関数の実行時の権限] が 異なることがある ---- FOOTER::参考:実行コンテキストの権限と関数の実行時の権限? JavaScriptの関数は 自分自身がどの権限で 定義されたものかを 知っている ---- サンドボックス内で 定義された関数 ↓ [実行する]時も常に セキュリティ制限[あり] ---- [[image src="context1.png" width="914" height="474"]] FOOTER::サンドボックス内で定義された関数はセキュリティ制限を受ける ---- FOOTER:: サンドボックス外で 定義された関数 ↓ [実行する]時も常に セキュリティ制限[なし] ---- [[image src="context2.png" width="914" height="474"]] FOOTER::サンドボックス外で定義された関数は特権を持っている ---- FOOTER:: ある関数から 別の関数を 呼び出すと どうなる? ---- サンドボックスの中で 定義された関数Aが サンドボックスの外で 定義された関数B'を実行 ---- サンドボックスの 外で定義された 関数B'は [サンドボックス外]の[権限] を持っている ---- 関数B'は [セキュリティ制限]を [受けない] ---- 関数Aが 関数B'を 使えば ---- 関数Aは サンドボックスの 制限を超えて 処理結果を得られる ---- [[image src="context3.png" width="914" height="474"]] FOOTER::サンドボックス外で定義された関数はセキュリティ制限を受けない ---- FOOTER:: つまり ---- Firefox内部 (サンドボックス外) で定義された関数を ---- Webページの中 (サンドボックス内) に放り込んだら ---- Firefox内部の 権限で色々される 可能性が出てくる ---- 危険 な例 ---- Webページ内の スクリプトの権限 ではできないことを 無理矢理可能にする (古いGreasemonkey) ---- 脆弱性 ---- XMLHttpRequest のセキュリティ制限 を回避できてしまう ---- XMLHttpRequestって? Greasemonkeyって? ---- FOOTER::参考:XMLHttpRequestとは? [[EM:XMLHttpRequest:EM]] JavaScriptによる非同期 [通信]を可能にする機能 Ajaxなどで 利用されている ---- サンドボックス内の権限 ↓ [そのWebページのあるサーバ] としか通信できない ---- サンドボックス外の権限 ↓ [他のサーバ]とも通信できる [ローカルファイル]も読み込める ---- FOOTER::参考:Greasemonkeyとは? ユーザースクリプト機能を Firefoxに加える拡張機能 [[Greasemonkey|http://greasemonkey.mozdev.org/]] ---- ユーザースクリプトで [Google]や[Amazon]などの サービスを使えるように GM_xmlhttpRequest という独自の関数を定義 ---- [[EM:GM_xmlhttpRequest:EM]] サンドボックス外で定義され サンドボックス外の権限で 動作する関数 ---- 関数内では XMLHttpRequest をFirefox内部の 権限で実行 ---- FOOTER:: 脆弱性 が発覚 ---- GM_xmlhttpRequest はユーザースクリプト からしか実行できない ように設計されていた ---- 通常は Webページ内の スクリプトから は呼び出せない ---- ここに 落とし穴 ---- サンドボックス外の関数 GM_xmlhttpRequest を [Webページ内の変数] ([サンドボックス内の変数]) に一瞬だけ代入していた ---- その隙をついて GM_xmlhttpRequest を Webページ内の関数 (サンドボックス内) から呼び出せる ---- つまり ---- Webページの スクリプトから ローカルファイルにも 他のサーバにも アクセスし放題 ---- 個人情 報漏洩 の危険 ---- 改善 ---- Webページの中に 危険な関数を 置かない ---- 独自の サンドボックス内で ユーザースクリプトを 実行するよう 設計を変更 ---- 詳しくは Greasemonkeyの [[dochandler.js|http://www.mozdev.org/source/browse/~checkout~/greasemonkey/src/content/dochandler.js?content-type=text/plain]] を読んでください ---- ややこしいので 解説しません ---- HEADER:: CHAPTER::危険要素4:自分で個人情報を漏らしてしまう それ以外 の危険性 ---- HEADER::それ以外の危険性 自分で 個人情報を 漏らして しまう危険 ---- 危険 な例 ---- ユーザースクリプト をWebページ内に そのまま埋め込む という設計 (古いGreasemonkey) ---- [自動ログイン]などのために ユーザースクリプト内に [パスワード]を書いていると [ページ作者]に知られる 可能性がある ---- 改善 ---- ユーザースクリプト をWebページ内に 埋め込まないように 設計を変更 ---- 作る側 として ---- Webページ内に 何かを追加する 前によく考えよう ---- 使う側 として ---- 拡張機能の [動作原理]を 知らないと 危険に 気付かない ことがある ---- 個人情報の 扱いは 慎重に! ---- CHAPTER::対策 HEADER:: 危険性の話は ここまで ---- 対策 ---- セキュリティ 対策のための 注目の機能 ---- HEADER::注目の機能 XPCNativeWrappper ---- HEADER::注目の機能:XPCNativeWrappper 関数・変数の 影響する範囲 を完全に分断 ---- サンドボックス内と サンドボックス外で [同じオブジェクト]に [アクセス]できない ようにしてしまう ---- サンドボックス外で 定義した関数などを [Webページ内の変数] に代入しても ---- [Webページ内の関数] ([サンドボックス内]) からは見えない ---- 逆に ---- サンドボックス 内で定義された 変数や関数も サンドボックス外 からは見えない ---- [[image src="xpcnativewrapper.png" width="914" height="474"]] FOOTER::XPCNativeWrapperによってサンドボックス内外が分断された状態のイメージ ---- FOOTER:: 古いGreasemonkey の脆弱性のような 問題は原理的に 起こり得ない ---- 欠点 その1 ---- サンドボックス内外で 情報を共有できない ---- FOOTER::欠点:サンドボックス内外で情報を共有できない 回避 方法 ---- [JavaScript]の [変数や関数の影響範囲] は分断されているが ---- 処理対象の Webページ 自体は共通 ---- Webページの ソースに加えた変更は サンドボックス内外に 共通して影響する ---- ソースコード =[文字]情報 ---- つまり [XMLの文書片]や [要素ノードの属性] として[文字情報] は共有可能 ---- JavaScriptを 使った処理も 一部は共有可能 ---- [Window.setTimeout()]や [Window.setInterval()]に [文字列]として渡した JavaScript文は サンドボックス内 で実行される ---- [onclick]属性などで [イベントハンドラ]を 要素に指定した場合も JavaScript文 を共有できる ---- [data: URL]と [Base64エンコード] を使えば一部の バイナリ情報も 共有できる ---- サンドボックス内→外 [CGIスクリプト]などで data: URLに変換 ---- サンドボックス外→内 [JavaScriptとXPCOM]で data: URLに変換 (例:[[画像の変換|https://piro.sakura.ne.jp/xul/lib/src/pImageLoader.js]]) ---- ただし 当然ながら ---- 文字情報に できないものは 共有できない ---- FOOTER:: 欠点 その2 ---- サンドボックス外の 権限を必要とする機能を サンドボックス内では 使えない ---- FOOTER::欠点:サンドボックス内外でJavaScriptのオブジェクトを共有できない 関数は [実行時の権限] まで含めては 文字情報に 変換できない ---- オブジェクト そのものも 共有できない ---- 回避 方法 ---- xpcnativewrappers=no フラグ ---- 拡張機能などの インストール定義で セキュリティ制限を 回避する指定 ---- xpcnativewrappers=noフラグの タブブラウザ拡張での使用例 [[PRE: content tabextensions_eventhandler jar:chrome/tabextensions.jar!/content/eventhandler/ xpcnativewrappers=no :PRE]] (実際には1行に書く) ---- 今まで通り サンドボックス内外で 変数や関数の影響範囲 を共有できる ---- ただし 当然ながら ---- XPCNativeWrappper の恩恵にあずかれ ないので ---- サンドボックス内外を またいで関数を実行できる 脆弱性を仕込まないように 気を遣う必要がある ---- HEADER:: FOOTER:: その他 ---- [[SplitWindow|http://wiki.mozilla.org/Gecko:SplitWindow]] ([[Bug 296639|https://bugzilla.mozilla.org/show_bug.cgi?id=296639]]) ---- セキュリティの 画期的な向上 らしい ---- 英語読めません 意味分かりません (XPCNativeWrapper の話と誤解してた) ---- 誰か教えて ください ---- HEADER:: FOOTER:: CHAPTER::クロージング 以上 ---- HEADER:: ご静聴 ありがとう ございます ---- 質疑 応答