| ←前のページ | トップ |
昨日「Sage 1.4.5 に今も残る深刻な脆弱性について」書いたことを開発者ブログのコメント欄を通じて作者に連絡したところ「再現方法を教えて欲しい」とのことでしたので早速テストファイルを送りました。なので近いうちに修正版がリリースされると思います。と、そんなやり取りをしていた矢先、これまでサンドボックスに入っていたはずの本家Sageが、いつの間にかAdd-ons for Firefox (AMO)のサイト上で通常公開されてしまっていました。
種明かしをすると、昨日のような日本語+(拙い)英語の長文エントリをSageの最新版が公開されたその日に書き上げることができるわけもなく、あれは先月24日にバージョン1.4.4がリリースされてから少しずつ書き進めていたものに1.4.5で更新された内容を加筆したものです。実は1.4.4において脆弱性が修正されていないことはリリース直後に把握していましたが、作者によると「Firefox 3.6 compatibility release following shortly」とのことでしたので公開は保留していました。ですが、恐らくバージョン1.4.5になっても脆弱性が修正されない可能性も十分にあり得ると踏んでいました。そして実際その通りになったわけです。
昨日書いた問題点のうち、不正なリンクURIを使った攻撃については発見者によって脆弱性の実証が可能なテストファイルを含む形で公開されていますし、それ以外に関しても(当時とは若干状況が違いますが)3年前に私がIPAを通じて報告した脆弱性の中に類似のものが含まれています。これが、先のエントリに「一体何を修正して何を確認したのか、大いに疑問を感じざるを得ません」と書いた所以です。
しかし、それ以上に今回疑問に思ったのは「AMOにおけるアドオンの審査体制はいったいどうなっているのか」ということです。
今回の経緯を見ていくと(かなり推測が入っていますが)、まずWizz RSS News Readerの作者であるMike Kroger氏に対してAMOのレビュアーから「2週間以内に脆弱性の修正のみならず『十分安全』な状態にし、かつ最新のアドオンポリシーに完全に従わなければサンドボックス送りにする」という警告が送られたことに端を発します(*1)。その高飛車な態度に彼はぶち切れてAMOから彼のアドオン(Sage-Tooを含む)を削除してしまったわけですが、本家Sageがサンドボックスに入れられたのも丁度その頃だったように記憶しています。恐らく一方だけを特別扱いするわけにはいかなかったからでしょう。
その後、Mike氏はAdBlock Plusの作者であり、脆弱性の発見者でもあるWladimir Palant氏のアドバイスに従って nsIScriptableUnescapeHTML#parseFragment によるサニタイズ処理を実装するわけですが、その過程で、そのメソッドだけでは数年前に修正したはずの別の脆弱性が再発してしまうことに気づきます(*2)。結果として彼はそのメソッドと独自の処理の組み合わせによって脆弱性を修正したバージョンを彼自身のサイト上で公開しました。
一方、本家Sageの作者は、単純に nsIScriptableUnescapeHTML#parseFragment を採用しました。そして既に報告されていた内容を確認すれば簡単に発見できたはずの脆弱性を見過ごし、それを「security improvements」と称してリリースしました。
――今日現在、前者はAMOから削除され(本人が削除したわけですが)、後者は晴れてサンドボックスから出て通常公開されています。
ここから分かることは、AMOのレビュアーと言われる人々は実際にそのアドオンに問題があるかどうかには殆ど関心がなく、もっぱら機械的に「○○メソッドを使っていればOK」「△△メソッドを使っていればNG」という白黒判定しかしていないのではないかということです(*3)。実際、Bugzillaで公開されているファイル[ZIP]を使えば1分で発見できる脆弱性を見過ごしているわけですから。
勿論、星の数ほどあるアドオンをいちいち隅から隅までチェックしろなどと言うつもりはありません。しかし、何かの理由があって一度サンドボックス送りにしたアドオンを再び通常公開するときくらいは、もう少し慎重に検証した方がいいのではないでしょうか。
そして、nsIScriptableUnescapeHTML#parseFragment の問題点を把握してもいないのに他人のアドオンに口出しするのみならず、レビュー方針全般にも影響を与えていると思しきWladimir Palant氏とはいったい何者なのでしょうか。そんなに偉い人なのですか(誰か教えて下さい)。
ましてや広告ブロックは「他人の権利を踏みにじる行為」と考えているMike氏にとって、そんなアドオンを作っている人間から(中途半端に間違った知識で)文句を付けられたことには相当腹に据えかねるものがあったとしても不思議ではありません(勝手な想像です、念のため)。
かく言う私は、これまで一貫してこのひまグをSage++の唯一の公開場所としています。Sage++はもともと本家Sageに「フィードを新しいタブで開く」という機能を付け加えたことに端を発し、それが本家Sageに脆弱性が発見されたことでこちらも対応を余儀なくされ、そんなこんなでずるずると続いて今に至るわけですが、元を正せば「他人のアドオンを自分の好きなように改造しただけ (=Higmmer's Edition)」に過ぎないものを、あたかも自分の成果物であるかのようにAMOに登録するのは違うと思ったこと、それがその理由です。
そしてもうひとつの理由として、AMOの中の人やそれに関連する動きに振り回されたくないという思いがあります。今回の一連の動きを見て、その思いを更に強くしました。
ですがユーザーの方にとってみれば「AMOへの登録を拒んでいるひぐまは信用ならん、奴が作ったアドオンなど使いたくない」と思われても仕方ないでしょう。ましてや作者は過去にこんな問題を起こしたこともある人物なわけで、それは当然の判断だと思います。実際、piro氏も指摘している通り、Firefoxのアドオンとは「Firefox自体を改造するパッチ」そのものであり、ひとつ間違えば深刻な問題を引き起こす可能性を常に内包しているわけで、その導入・使用に当たってはどんなに注意してもし過ぎることはありません。
ですから、一般論として、信頼に足ると思われる複数の人物によるチェックを受けたアドオンが登録されていると考えられるサイトを選択するのは賢明な判断です。少なくともこんな野良サイトに転がっている野良アドオンに手を出すことに比べれば、そのリスクはずっと低いでしょう。
ですが、そんなチェックを経たはずの、しかもサンドボックスからも出されているアドオンの中に、既に報告済みの脆弱性が何年にもわたって放置され続けているものが含まれている――という事実は知っておいた方がいいでしょう。
※
……なんだか書いているうちに「ひぐまは本家Sageを潰したいと思ってる」と受け取られかねない文章になってしまいましたが、そんな意図は毛頭ありません、というか逆に潰れて欲しくありません。膨大な数に上ると見られる本家Sageのユーザー達が乗り換え先を探してSage++に雪崩れ込んできたりでもすればとてもじゃないですが対応できるわけありませんから(^^;
本家よりFirefox 3.6対応版の Sage 1.4.5 がリリースされました。開発者ブログによると「セキュリティを改善した」とのことなので早速テストしてみました。
その結果、このバージョンにおいても依然として幾つかの脆弱性が残っていることを確認しました。
Roberto Suggi Liverani氏が報告した脆弱性のうち、link要素内に特殊なURIを埋め込む攻撃に対して依然として脆弱ですし、それどころか、後述のようにエントリ本文に対して従来よりも簡単にスクリプトを埋め込むことができるようにさえなっています。一体何を修正して何を確認したのか、大いに疑問を感じざるを得ません。
公平のために付言すれば、一応セキュリティ面において若干の改善が行われたのは事実のようですが、残念ながらその改善はこれらの脆弱性に対しては効果を発揮していません。一体どこに問題があるのか、ポイントは3つあります。
Sage 1.4.4 以降では、それまで実装していたオレオレ構文解析器 正規表現によるHTMLフィルタを捨て、Firefox本体に備わっているAPIを使ってエントリ本文のフィルタリング処理を行うように変更されています。コードで示すと以下の通りです。
var sanitizer = Cc["@mozilla.org/feed-unescapehtml;1"].getService(Ci.nsIScriptableUnescapeHTML);
var fragment = sanitizer.parseFragment(item.getContent(), false, null, document.documentElement);
ds = new XMLSerializer().serializeToString(fragment);
これはAdBlock Plusの作者も推奨している方法で、過去には「JavaScript の除去には nsIScriptableUnescapeHTML を使え(?)」とも言われており、一見何の問題もないように見えます。しかしFirefox 3以降での仕様変更なのかバグなのかは定かではありませんが、現行の nsIScriptableUnescapeHTML#parseFragment は一部の属性(値)内にスクリプトが記述されていてもそれを除去しないようです(*1)。つまりわざわざフィルタをすり抜けるようにフィードに小細工をしなくても正々堂々と(?)スクリプトを注入することが可能となります。はっきり言ってこれでは元のオレオレ構文解析器より部分的には弱くなってしまっています。
ちなみにSage-Too/Sage++では nsIScriptableUnescapeHTML#parseFragment ではなく nsIDOMNSRange#createContextualFragment を使ってDOMツリーを構築していますが、XHTMLの出力前にツリー上の全てのノードを自前で走査してホワイトリストで許可されていない要素・属性を除去する処理を行っています。
また、そもそもの問題としてフィード内の全ての要素が前記のフィルタで処理されているわけではないという問題があります(*2)。その代わり不正な文字などを確実にエスケープすれば問題はないのですが、Sage 1.4.4以前ではそれも不十分でした(Sage 1.4.5で対策が施されました)。
Sage-Too/Sage++でもそれらの部分に対してはDOMフィルタによる処理は行っていませんが、代わりに問題を起こす可能性のある文字をXHTML出力の直前段階で徹底的にエスケープしているのに加え、不正なリンクURIを検出した場合はそれを除去する処理などを加えることで安全性を確保しています。
しかしSage 1.4.5ではリンクURIの検査が不十分なため、依然として特殊なURIを用いた攻撃が可能なままです。
そしてこれが最悪なのですが、以前にも書いた通り本家Sageではchromeスキームで開いたページにフィードを直接書き出しているため、ひとたびスクリプトの侵入を許すと攻撃者はFirefoxの動作を完全に乗っ取り、ありとあらゆる攻撃を行うことが可能となるという重大な危険性があります。
ではどうすればいいのか。 AdBlock Plusの作者は type="content" 属性を指定した browser 又は iframe 要素を使う方法を提唱しています。そのような要素を作成してその中にフィードから生成したHTMLを流し込むようにすれば、たとえそこにスクリプトが混入したとしても、それらがchromeとコンテンツの境界を越えてより上位のウィンドウ、つまりFirefox本体にアクセスすることはできなくなります(*3)。実はこれはFirefox自身が行っているのと同じ方法でもあります。
具体的には "feedsummary.html" を以下のように変更します。
<body>
<!-- これを追加 -->
<iframe id="feed-frame" type="content" style="border:none;width:100%;height:100%;></iframe>
</body>
そして "feedsummary.js" の "displayFeed" 関数を以下のように変更します。
displayFeed: function (feed)
{
document.title = feed.getTitle() + " - Sage";
//document.body.innerHTML = CreateHTML.createHTMLSource(feed);
document.getElementById("feed-frame").contentDocument.body.innerHTML = CreateHTML.createHTMLSource(feed);
},
たったこれだけで悪意あるスクリプトがchrome特権モードで動くことを防止することができます(実験で確認済み)。
但し実際はこの変更を行うとデフォルトCSSが適用されなくなるという副作用がある(コンテンツからchromeパッケージ内のファイルにアクセスできなくなるため)ので更に若干の変更が必要になります。
参考までに、本家 Sage 1.4.5 にそれらの変更を施して一応動作する状態にしたXPIパッケージを以下に置いておきます。但しこれはあくまでもスクリプトの権限昇格を防止するだけであり、スクリプト侵入の脆弱性そのものを修正するものではないので注意して下さい。
注:本バージョンにはユーザーCSSが使用できないという不具合があります
(chromeとコンテンツの境界を越えてローカルファイルにアクセスできなくなったため)
※
尚、くどいようですがSage-Too/Sage++ではフィードの表示にchromeスキームではなくfileスキームを使用しています(*4)。そのため仮にスクリプトの侵入を許したとしてもそれが特権モードで動作することはありませんが、ローカルファイルの読み取りなど一部の攻撃は可能となる恐れがありますので、心配ならばこのページの情報を見て適切な対策を取ることを推奨します。
本日、Sage++ (Higmmer's Edition) 2.2.0を正式リリースしました。今回のバージョンより Firefox 3.0.xと3.5.xに再対応し、Firefox 3.0〜3.6のバージョンにて利用できるようになりました。これらのバージョンにおいて既にSage++がインストールされている場合はアドオンの更新を行うことで自動的にアップデートされます。
手動でのインストールは下記配布ページより行うことができます。
- Firefox 3.0/3.5/3.6に対応
- OPMLインポート直後に更新カウンタが乱れる問題を修正
- フィード解析における日時の解釈を柔軟化
- RFC822/ISO8601で解釈できない場合は他方を試みる
- RFC822においてタイムゾーン指定子"Z"と"JST"に対応
- ISO8601において
- 日付と時刻の区切りが"T"でなく空白の場合に対応
- 時刻が指定されてない場合は"00:00"とみなす
- 時刻があってタイムゾーンがない場合はローカルタイムが指定されたものとみなす
以前のバージョンにおいて、フォルダ上に更新カウントを表示している状態でOPMLインポートを行った後、すぐに追加されたフィードを開くとそのフィードより上位のフォルダの更新カウントが壊れるという不具合がありました(*1)。この問題は今回のバージョンで修正されました。
また、本バージョンよりフィード解析における日時の解釈をより柔軟に行うようにしました。これによりある程度規格外のフォーマットにも対応可能になりました(*2)。但し、ISO8601においてタイムゾーン(時刻ありの場合は必須)が指定されていない場合にローカルタイムを仮定することには賛否両論ありそうです。本来ならばこのような場合は協定世界時(UTC)として処理するのが正しいかとも思われますが、ユーザーの実使用環境においてはローカルタイムを仮定するのがより現実的と判断しました(*3)。
これによって問題が生じるフィードを発見した場合は作者までご連絡頂ければ対応を検討します。
サイトによってはお知らせなどを常にトップに表示させることを意図して未来の日時を設定していることがあるようです。このような場合Sage++では正しい更新判定ができないことがあります(*4)。申し訳ありませんが今の所これに対応する予定はありません。理由は以下の通りです。
フィード毎に更新の判定方法をカスタマイズできるようにすることも一時検討しましたが、作者がそこまでの必要性を感じていないため手付かずとなっています。
ちなみに現在のSage++においても、フィード内の各エントリが日時情報を持っていない場合は代わりにタイトルから生成したシグネチャを比較する方法で更新判定を行っています。そこでYahoo! Pipesでこんなものを用意しました。
フィードをこのPipeに通すと各エントリの日時情報が除去されます。つまりこの出力結果をSage++で購読すれば、日時ではなくタイトルの更新を検出して更新判定を行うようになるはずです。残念ながら作者は具体的なフィードの実例を知らないので意図通り動くかどうかは確かめていませんが、もしよかったら試してみて下さい。
Firefox 3.6対応版 Sage++ (Higmmer's Edition) 2.2.0pre2 をリリースしました。例によってインストール及び使用にあたっては自己責任でお願いします。
※Firefox 3.6でSage++を導入済みの場合は「更新を確認」で自動的に更新されます。
- Firefox 3.6での以下の不具合を修正
- フィードアイコンがfaviconに化けることがある
- ライブブックマークとして登録されているフィードアイコンがフォルダアイコンに化ける
- OPMLインポート時に「応答のないスクリプト」警告ダイアログが表示されることがある
OPMLインポート中に無反応状態になってしまうことへの対策として今回から処理を擬似的なマルチスレッドで行うようにしました。但しその副作用として(→ これに関係なく以前から発生していた不具合でしたorz。次回リリースで修正予定)インポート直後にフォルダ上の更新カウントがおかしくなることがある不具合があります。もしそうなった場合は一旦Sage++のサイドバーorウィンドウを閉じて開き直して下さい。
If you have concern about the security and/or vulnerabilities of Sage series, please read this entry to get some information.
大変長らくお待たせしました。Firefox 3.6に対応した Sage++ (Higmmer's Edition) 2.2.0pre1 を本日リリースします。但しまだ幾つかのバグが残っているのと動作確認が不十分なためプレリリース版という位置付けです。何か問題が起こっても自力で対処可能な方のみインストールするようにして下さい。
インストールを行う前にプロファイルをバックアップの上、新規プロファイルを作成することを推奨します。以前のバージョンのプロファイルを引き継いだ場合に何が起こるかは未検証です。
現在プレリリース版につき旧バージョンからは自動更新されませんので上記リンクから手動でインストールして下さい。
その他、バグや不具合と思われる挙動を発見した方はこのエントリのコメント又はメールフォームにてご連絡頂ければ助かります。
Sage++のFirefox 3.6対応は本当はRC版がリリースされたらすぐに行うつもりだったのですが、間の悪いことに丁度パソコンが故障したため新しいマシンへの移行が必要になったのに加え、運悪くインフルエンザにかかったりなどしたため、結局ほぼ一週間近く殆ど作業できない状態に陥ってしまっていました。そんなこんなしてる間にFirefox 3.6の方も正式リリースが延期されたのでなんとか間に合わせることができたわけですが(^^;
実を言うと私自身はメインで使うフィードリーダーを既にWeb型に切り替えていて、Sage++はリアルタイムに確認したいごく一部のフィードでしか利用していません。また、Firefox 3.6が正式リリースされても当分の間は現行のFirefox 3.5を使い続ける予定です(正直そんな頻繁なバージョンアップにはついていけない)。なので、Firefox 3.6対応版のSage++の開発作業を急ピッチで継続するつもりはありません。もしかするとこのまま正式バージョンを出さないままフェードアウトする可能性もあります(「作者が使わないソフトは放置される」の法則)。
| ←前のページ | トップ |