ククログ

株式会社クリアコード > ククログ > FirefoxのDisableThirdPartyModuleBlockingポリシーとSKYSEAの競合と、その回避

FirefoxのDisableThirdPartyModuleBlockingポリシーとSKYSEAの競合と、その回避

結城です。

Firefox 110以降(ESR版ではFirefox ESR115以降)において利用可能になったポリシー設定の1つに、DisableThirdPartyModuleBlockingがあります。 この度、SKYSEAを導入されているお客さまの環境でこのポリシー設定を有効化しようとして、SKYSEAとの間で互換性の問題が発生しました。 以下、このポリシー設定がどのような意味を持つ物なのか、SKYSEAとどのように競合するのか、そして、競合をどのようにすれば回避できるのかを解説します。

DisableThirdPartyModuleBlockingのはたらき

このポリシー設定の機能を説明する前に、そもそも、Firefox 110以降で可能になった「ユーザーレベルでの外部モジュール無効化」機能について説明します。

Firefoxには従来から、about:third-partyという機能があります。 アドレスバーにこのURIを入力してEnterを押して開くと、現在読み込まれているFirefox外のDLL(動的に読み込まれるライブラリ)が列挙されるという物で、トラブル発生時の原因究明などに役立つことが期待されているようです。 実際にお手元の環境で開いてみると、日本語入力ソフトのDLLなどが列挙される様子を確認できるはずです。

またFirefoxには、そういったDLLで脆弱性やクラッシュする不具合を含んでいることが知られている物など、既知の問題がある外部モジュールのブロックリストが静的に組み込まれていて、ブロックリストに該当する外部モジュールは無効化されるようになっています。 about:third-partyは、このブロックリストの効果を確認するUIとしても機能します。

ただ、このブロックリストの変更はFirefoxの再ビルドを要するため、新たにクラッシュが頻発するようになった外部モジュールに対しては無力です。 ユーザーの立場では、問題をMozillaに報告し、ブロックリストに追加してもらって、次のリリースに反映されるのを待つしかありません。

そこでFirefox 110では、about:third-partyから任意のモジュールをユーザーの判断で無効化できる機能が加わりました。 about:third-partyを開くと「生データをクリップボードにコピー」ボタンの右にくるくる回るアニメーションのアイコン(「システム情報を読み込んでいます…」というツールチップが表示される物)が表れ、しばらく待つとアイコンが消えて「システム情報を更新」というボタンが表示されますが、この「システム情報を更新」をクリックすると、モジュール一覧が更新されると同時にそれぞれの項目の横に「このモジュールをブロック」というボタンが表れます1。 このボタンを押すと、対象モジュールの情報を動的なブロックリスト2に登録した後にFirefoxが再起動して、以後はそのモジュールが無効化される、という具合です3

(画像:about:third-partyに「このモジュールをブロック」ボタンが表示されている様子のスクリーンショット。)

ところが、法人利用ではここで1つ問題があります。 このようにして読み込まれる外部モジュールの中には、Firefoxの動作を監視するSKYSEAのように、「クラッシュするなどのリスクがあっても、法人運用のセキュリティポリシー上は常に有効にしておかなくてはならない」といった物があるため、ユーザー判断で勝手に無効化されてしまっては困るのです。

その対策として導入されたのが、DisableThirdPartyModuleBlockingというポリシーです。 このポリシーが設定されていると、Firefoxは前述の動的ブロックリストを使わないようになり、また、about:third-partyからのモジュール無効化操作も行えない(「このモジュールをブロック」ボタンが表示されない)ようになります。 これにより、法人運用上のポリシーを遵守できるという寸法です。

Firefoxの起動処理の設計上の制約のため、このポリシーはpolicies.jsonでは指定できず、必ずActive Directoryのグループポリシーで設定する必要があります。 具体的には、ポリシーテンプレート導入後に、「管理用テンプレート」→「Mozilla」→「Firefox」→「Disable Third Party Module Blocking」を「有効」に設定します。 また、Active Directoryを運用していない環境でも、レジストリーのHKEY_LOCAL_MACHINE\\SOFTWARE\Policies\Mozilla\Firefox配下にDWORD型の値DisableThirdPartyModuleBlockingを作成し、データを1に設定すれば、同じ効果を得られます。

SKYSEAとの競合

Firefoxの仕様としては以上の通りなのですが、SKYSEA運用環境下で実際にこの通りに運用しようとすると、SKYSEAが期待通りに動作しないという競合が発生します。 以下は、SKYSEAアドオンのバージョンが17.2.10.268と認識される状況での調査結果に基づく説明です。 SKYSEAのバージョンによっては異なる結果となる可能性もありますのでご注意ください。

お客さまの検証用環境で検証した際には、SKYSEAが有効な環境において、ポリシー設定によって制御されているFirefoxを起動すると、以下のことが起こる様子でした。

  1. policies.jsonに以下の情報が書き込まれる。
    • policies.Extensions.Installに、Firefox用SKYSEAアドオンをローカルファイル(C:\Program Files (x86)\Sky Product\SKYSEA Client View\FxAddonSigned\skysea-fxaddonWebExt2.xpi.17.2.10.268)からインストールする記述が追加される。
    • policies.Extensions.Lockedに、Firefox用SKYSEAアドオン(識別子 addon-firefox-WebExt2@skysea.skygroup.jp)をロックする記述が追加される。
  2. HKEY_LOCAL_MACHINE\\SOFTWARE\Policies\Mozilla\Firefox\Extensions配下に以下の情報が書き込まれる。
    • HKEY_LOCAL_MACHINE\\SOFTWARE\Policies\Mozilla\Firefox\Extensions\Installに、名前が1、データがC:\Program Files (x86)\Sky Product\SKYSEA Client View\FxAddonSigned\skysea-fxaddonWebExt2.xpi.17.2.10.268である文字列型の値が追加される。
    • HKEY_LOCAL_MACHINE\\SOFTWARE\Policies\Mozilla\Firefox\Extensions\Lockedに、名前が1、データがaddon-firefox-WebExt2@skysea.skygroup.jpである文字列型の値が追加される。

SKYSEAアドオンはFirefox上でのWebブラウズの様子(どのURLを訪問したか)を記録するために使われる物らしく、確実にFirefoxの使用動向を監視するべく、ポリシー設定を上書きしてSKYSEAアドオンを強制的にインストール・有効化するために、このような処理を行っているのだと思われます。

しかしながら、検証の結果、この動作がDisableThirdPartyModuleBlocking指定と競合する様子であることが分かりました。 具体的には、HKEY_LOCAL_MACHINE\\SOFTWARE\Policies\Mozilla\FirefoxにDWORD型の値DisableThirdPartyModuleBlockingが存在する状態でFirefoxを起動すると、SKYSEAによる前述の1の処理は行われるものの、2の処理に失敗するためか、「キーHKEY_LOCAL_MACHINE\\SOFTWARE\Policies\Mozilla\Firefox\Extensionsは作成されるが、その配下に何も情報がない状態」が発生する様子でした。

この時、Firefoxの動作は以下のようになり、SKYSEAアドオンによるFirefoxの使用状況の監視を徹底できなくなってしまいます

  • Firefoxは、空のキーHKEY_LOCAL_MACHINE\\SOFTWARE\Policies\Mozilla\Firefox\Extensionsを「グループポリシーによって、アドオンを何もインストールせず、ロックせず、アンインストールもしないように設定された状態」と解釈する。
  • Firefoxはpolicies.jsonよりもグループポリシー(Windowsレジストリ)由来の指定の方を優先的に反映するため、policies.jsonがどのようになっているかにかかわらず、「アドオンを何もインストールせず、ロックせず、アンインストールもしない」動作となる。
    • この状態になる前にFirefoxが起動されていた場合、SKYSEAアドオンはユーザープロファイル内にインストールされているため、SKYSEAアドオンは一応動作し続ける状態となる。
      • しかしながら、SKYSEAアドオンはロックされていない状態になっている。そのため、ツールバー上の「拡張機能パネル4」などからユーザー権限でSKYSEAアドオンをアンインストールできてしまう
      • アンインストールされたSKYSEAアドオンを再インストールするための情報が無いため、SKYSEAアドオンは再インストールされないままとなる。よって、Firefox上でのWebブラウズ操作の監視も行われなくなる
    • この状態になってから(トラブル解消などのために)Firefoxのユーザープロファイルが削除されたり、新規にFirefoxを使い始めたりすると、SKYSEAアドオンはインストールされないままとなる。
      • SKYSEAアドオンがインストールされないままのため、Firefox上でのWebブラウズ操作の監視も行われなくなる

かといって、DisableThirdPartyModuleBlocking指定を除外することもできません。 SKYSEAはFirefoxに対して、アドオンを登録するだけでなく、外部モジュール(DLL)も読み込ませている様子なのですが5、このSKYSEAのモジュールをユーザーがabout:third-partyを使って任意に無効化できてしまう状態になるため、この場合もやはり、SKYSEAによるFirefoxの監視が徹底されなくなってしまう恐れがあります

競合を回避する

調査の結果、この問題を回避する方法はいくつかあることが分かりました。 しかし、それぞれにはメリットとデメリットがあります。

方法1:ポリシーの代わりに起動オプションを使う

外部モジュールのブロックについての開発者向けドキュメント中に記載がありますが、Firefoxに--disableDynamicBlocklistというコマンドラインオプションを指定することで、DisableThirdPartyModuleBlockingポリシーが指定されたのと同じ状態でFirefoxを動作させることができます。 例えば以下の要領です。

"C:\Program Files\Mozilla Firefox\firefox.exe" --disableDynamicBlocklist

実際の運用においては、Firefox起動用のショートカットのリンク先やランチャーの項目をこのように設定する、という事になるでしょう。

この方法のデメリットは、「それらのショートカットやランチャーを使わずに直接firefox.exeを起動すれば、容易に制限を回避できてしまう」という点です。 SKYSEAの導入ニーズを考慮すると、容易に回避できてしまう抜け道がある方法は採用しづらく、この方法は現実的ではない場合が多いと考えられます。

方法2:Extensionsポリシーの内容をすべて手動で指定する

SKYSEAがレジストリの編集に失敗するという現象に対し、設定されることが期待される内容が分かっているのであれば、それに相当する情報を最初から設定しておく、という方法は有効な対策として機能します。 GPOでの設定は以下の要領です。

  • 「管理用テンプレート」→「Mozilla」→「Firefox」→「Extensions]→「Extensions to Install」を「有効」に設定し、リストの項目の1つとして C:\Program Files (x86)\Sky Product\SKYSEA Client View\FxAddonSigned\skysea-fxaddonWebExt2.xpi.17.2.10.268 を登録する。
  • 「管理用テンプレート」→「Mozilla」→「Firefox」→「Extensions]→「Prevent extensions from being disabled or removed」を「有効」に設定し、リストの項目の1つとして addon-firefox-WebExt2@skysea.skygroup.jp を登録する。

Active Directoryを運用していない環境では、相当する情報をWindowsのレジストリに直接書き込む事になります。 .regファイルの書式で表すと、書き込む必要がある内容は以下の通りです。

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox\Extensions]

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox\Extensions\Install]
"1"="C:\\Program Files (x86)\\Sky Product\\SKYSEA Client View\\FxAddonSigned\\skysea-fxaddonWebExt2.xpi.17.2.10.268"

[HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Mozilla\Firefox\Extensions\Locked]
"1"="addon-firefox-WebExt2@skysea.skygroup.jp"

この方法のデメリットは、「SKYSEAの仕様が変更された場合に、登録内容を都度追従する必要がある」という点です。

例を見ても分かるとおり、SKYSEAアドオンのインストールのためのファイルパスにはバージョン番号の文字列が含まれており、バージョン番号が変わると有効に機能しなくなることが容易に予想できます。 そのため、SKYSEAの更新時にはその都度、ファイルのパスに変化がないかを常に確認する必要が生じます。

また、そもそも「前述のレジストリーに適切に値を設定すればよい」ということ自体もSKYSEAの特定のバージョンのみの仕様である可能性があります。 そういったレベルでの変化にいち早く気付くためには、都度クリーンな環境で実際にSKYSEAを動作させ、その結果行われるレジストリーへの変更内容を詳細に把握しておく必要もあります。

方法3:ポリシーの代わりにMCDの実行可能コードを使って「モジュールをブロック」ボタンを隠す

Firefox ESR115の時点では、MCD(AutoConfig)での実行可能コードを用いたカスタマイズが機能する様子です。 これを使い、DisableThirdPartyModuleBlockingポリシーの動作を部分的に模倣することで、ポリシー設定に頼らず外部モジュールの無効化操作を行えないようにする方法があります。 例えば、以下の要領です。

// Firefoxインストール先に defaults/pref/autoconfig.js として設置
pref("general.config.filename", "autoconfig.cfg");
pref("general.config.vendor", "autoconfig");
pref("general.config.obscure_value", 0);
pref("general.config.sandbox_enabled", false);
// Firefoxインストール先に autoconfig.cfg として設置

// Firefoxの初期化処理の最後にフックを仕掛ける
Services.obs.addObserver({
  observe(aSubject, aTopic, aData) {
    const sheet = `
      /* about:third-party に含まれる「モジュールをブロック」ボタンを非表示にする */
      @-moz-document
        url-prefix("about:third-party"),
        url-prefix("chrome://global/content/aboutThirdParty.html") {
          *|*.button-block {
            display: none !important;
          }
        }
    `;
    // 上記指定をユーザースタイルシートとして読み込む
    const uri = Services.io.newURI(`data:text/css,${escape(sheet)}`, null, null);
    const { classes: Cc, interfaces: Ci } = Components;
    const SSS = Cc['@mozilla.org/content/style-sheet-service;1']
                  .getService(Ci.nsIStyleSheetService);
    SSS.loadAndRegisterSheet(uri, SSS.USER_SHEET);
  }
}, 'final-ui-startup', false);

この方法には、「実行可能コードをFirefoxのバージョンに合わせて都度追従する必要がある」「ブロックリストを外から持ち込まれるケースを防げない」という2つのデメリットがあります。

1つ目のデメリットは、XULアドオン時代の互換性問題とよく似ています。 ここに記載したコード例はFirefox ESR115を前提としているため、他のバージョンでは動作しない恐れがあります(実際、Firefox ESR102では動作しません)。 Firefoxのバージョンアップで動かなくなった時は、原因を調べてコードを修正しなくてはいけません。 また、修正で動作するようになればよいのですが、ここで使用しているのはFirefoxの内部APIのため、API自体が使用できなくなる可能性があります。 API以前に、そもそもMCDでの実行可能コードの組み込みという手法自体が使えなくなる可能性もあります。

2つ目のデメリットは、他の環境でabout:third-partyを使って作成したブロックリスト2を採取して、SKYSEA運用環境の同じ位置に設置された場合に、そのブロックリストが無視されず機能してしまうということです。 DisableThirdPartyModuleBlockingポリシーや--disableDynamicBlocklistオプションは、about:third-partyの「モジュールをブロック」ボタンを非表示にするだけでなく、Firefoxの起動時の処理自体に作用して、このブロックリストを読み込む処理をスキップする効果があります。 それに対し、本項での実装例はあくまで「モジュールをブロック」ボタンを非表示にするのみで、ブロックリストの読み込み処理をスキップする効果まではありません。

2つ目のデメリットについては、ブロックリストのファイルを削除する処理を、Windowsへのログオン時や定時処理など実行することで、ある程度のリスク軽減は可能です。 Windowsのレジストリのユーザー権限での編集が禁止されている限り、削除するべきブロックリストの位置は既定の %AppData%\Mozilla\Firefox\blocklist-* のみを想定すれば充分です。

まとめ

Firefox ESR115で追加されたDisableThirdPartyModuleBlockingポリシーの働きと、SKYSEA運用環境における競合の様子、および現時点で可能な競合の回避方法についてご紹介しました。

本記事では競合の回避方法として3つの対策を挙げてみましたが、どの方法にも一長一短あり、完全な対策とはならないことに注意が必要です。

本記事で挙げた互換性の問題がSKYSEA側で修正されれば、ここで挙げた対策は不要となると予想できます。 お客さまに伺ったところ、SKYSEAの公式のサポート対象となっているFirefoxのバージョンはまだFirefox ESR102までで、Firefox ESR115はサポート対象外だそうなので、今後のSKYSEAの更新でこの競合は解消される可能性もあります。 Firefox ESR102のサポート期限は今月26日までですので、Firefox ESR115への更新はギリギリまで控え、SKYSEA側が更新されるのを待つのが、最も無難な対応かもしれません。

当社では、Firefoxの法人運用におけるトラブルについて、原因究明や回避方法の調査などを有償にて承っております。 本記事の内容も、お客さま環境でのFirefox ESR115以降に際しての検証の過程で発覚したものです。 Firefoxの運用でお悩みの企業のご担当者さまで、このようなレベルでの調査・対応を必要とされている方は、お問い合わせフォームよりご相談ください

  1. Firefox ESR115ではボタンのアイコンのみ表示されます。

  2. 動的なブロックリストは、%AppData%\Mozilla\Firefox\blocklist-(Firefoxのインストール先ごとのCity Hash値)City Hashについては過去の記事を参照)の位置バイナリファイルとして作成されます。このファイルは、WindowsのレジストリのHKEY_CURRENT_USER\Software\Mozilla\Firefox\Launcherに書き込まれた(Firefoxのインストール先のフルパス)\firefox.exe|Blocklistという名前の値のデータとしてフルパスが記録されており、Firefoxは起動時にこのレジストリの値を参照してブロックリストを読み込んで、該当する外部モジュールを無効化した状態で起動するようになっています。

  3. 同様の手順で、無効化した外部モジュールを再度有効化することもできます。

  4. なお悪い事に、Firefox 15ではツールバー上の拡張機能パネルはBlockAboutAddonsポリシーの影響を受けず常に表示状態となっています。そのため、ユーザーによるアンインストール操作を防ぐことができません。

  5. 状況的に、前述のpolicies.jsonの書き換えなどは、このモジュールが行っているのではないかと推測されます。