# ブラウザ拡張機能の侵入テスト方法論
htARTE(HackTricks AWS Red Team Expert)でAWSハッキングをゼロからヒーローまで学ぶ htARTE(HackTricks AWS Red Team Expert) HackTricksをサポートする他の方法: - **HackTricksで企業を宣伝**したい場合や**HackTricksをPDFでダウンロード**したい場合は、[**SUBSCRIPTION PLANS**](https://github.com/sponsors/carlospolop)をチェックしてください! - [**公式PEASS&HackTricksのグッズ**](https://peass.creator-spring.com)を入手する - [**The PEASS Family**](https://opensea.io/collection/the-peass-family)を発見し、独占的な[**NFTs**](https://opensea.io/collection/the-peass-family)のコレクションを見つける - **💬 [Discordグループ](https://discord.gg/hRep4RUj7f)**に参加するか、[telegramグループ](https://t.me/peass)に参加するか、**Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks_live)をフォローする - **HackTricks**と**HackTricks Cloud**のgithubリポジトリにPRを提出して、あなたのハッキングテクニックを共有する
## 基本情報 ブラウザ拡張機能はJavaScriptで書かれ、ブラウザによってバックグラウンドで読み込まれます。それは自身の[DOM](https://www.w3schools.com/js/js_htmldom.asp)を持っていますが、他のサイトのDOMとやり取りすることができます。これは他のサイトの機密性、整合性、可用性(CIA)を危険にさらす可能性があります。 ## 主要コンポーネント 拡張機能のレイアウトは視覚化された際に最も見栄えが良く、3つのコンポーネントで構成されています。それぞれのコンポーネントを詳しく見てみましょう。

http://webblaze.cs.berkeley.edu/papers/Extensions.pdf

### **コンテンツスクリプト** 各コンテンツスクリプトは**単一のWebページ**のDOMに直接アクセスでき、したがって**潜在的に悪意のある入力**にさらされます。ただし、コンテンツスクリプトには、拡張機能コアにメッセージを送信する権限以外はありません。 ### **拡張機能コア** 拡張機能コアには、拡張機能のほとんどの権限/アクセスが含まれていますが、拡張機能コアは[XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)およびコンテンツスクリプトを介してWebコンテンツとのやり取りしかできません。また、拡張機能コアはホストマシンに直接アクセスする権限はありません。 ### **ネイティブバイナリ** 拡張機能には、ユーザーの完全な権限でホストマシンにアクセスできるネイティブバイナリが含まれています。ネイティブバイナリは、Flashや他のブラウザプラグインで使用される標準のNetscapeプラグインアプリケーションプログラミングインターフェース([NPAPI](https://en.wikipedia.org/wiki/NPAPI))を介して拡張機能コアとやり取りします。 ### 境界 {% hint style="danger" %} ユーザーの完全な権限を取得するには、攻撃者はコンテンツスクリプトから拡張機能コアへの悪意のある入力と、拡張機能コアからネイティブバイナリへの悪意のある入力を拡張機能に説得する必要があります。 {% endhint %} 拡張機能の各コンポーネントは、**強力な保護境界**によって互いに分離されています。各コンポーネントは**別々のオペレーティングシステムプロセス**で実行されます。コンテンツスクリプトと拡張機能コアは、ほとんどのオペレーティングシステムサービスには利用できない**サンドボックスプロセス**で実行されます。 さらに、コンテンツスクリプトは**別々のJavaScriptヒープ**で実行され、関連するWebページから分離されます。コンテンツスクリプトとWebページは**同じ基礎となるDOMにアクセス**できますが、2つは**JavaScriptポインタを交換することはなく**、JavaScript機能の漏洩を防ぎます。 ## **`manifest.json`** Chrome拡張機能は、[.crxファイル拡張子](https://www.lifewire.com/crx-file-2620391)を持つZIPフォルダーです。拡張機能のコアは、フォルダーのルートにある**`manifest.json`**ファイルで、レイアウト、権限、その他の構成オプションを指定します。 例: ```json { "manifest_version": 2, "name": "My extension", "version": "1.0", "permissions": [ "storage" ], "content_scripts": [ { "js": [ "script.js" ], "matches": [ "https://example.com/*", "https://www.example.com/*" ], "exclude_matches": ["*://*/*business*"], } ], "background": { "scripts": [ "background.js" ] }, "options_ui": { "page": "options.html" } } ``` ### `content_scripts` コンテンツスクリプトは、ユーザーが一致するページに移動するたびに**ロードされます**。この場合、**`https://example.com/*`**式に一致するページと**`*://*/*/business*`**正規表現に一致しないページです。これらはページ自体のスクリプトのように**実行され**、ページの[Document Object Model (DOM)](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model)に任意のアクセス権を持ちます。 ```json "content_scripts": [ { "js": [ "script.js" ], "matches": [ "https://example.com/*", "https://www.example.com/*" ], "exclude_matches": ["*://*/*business*"], } ], ``` **`include_globs`**と**`exclude_globs`**を使用して、さらにURLを含めたり除外したりすることも可能です。 これは、ページに説明ボタンを追加するコンテンツスクリプトの例です。これは、[ストレージAPI](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/storage)を使用して、拡張機能のストレージから`message`値を取得するために使用されます。 ```js chrome.storage.local.get("message", result => { let div = document.createElement("div"); div.innerHTML = result.message + " "; div.querySelector("button").addEventListener("click", () => { chrome.runtime.sendMessage("explain"); }); document.body.appendChild(div); }); ```
このボタンがクリックされると、コンテンツスクリプトによって拡張機能ページにメッセージが送信されます。これは、`storage`が例外の中にあるAPIに直接アクセスできないというコンテンツスクリプトの制限によるものです。これらの例外を超える機能が必要な場合、メッセージが拡張機能ページに送信され、コンテンツスクリプトが通信できます。 {% hint style="warning" %} ブラウザによっては、コンテンツスクリプトの機能がわずかに異なる場合があります。Chromiumベースのブラウザでは、機能のリストは[Chrome Developers documentation](https://developer.chrome.com/docs/extensions/mv3/content_scripts/#capabilities)で利用可能であり、Firefoxでは[MDN](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts#webextension_apis)が主要な情報源となります。\ また、コンテンツスクリプトはバックグラウンドスクリプトと通信する能力を持ち、アクションを実行し、応答を返すことができます。 {% endhint %} Chromeでコンテンツスクリプトを表示およびデバッグするには、Chromeの開発者ツールメニューにアクセスし、Options > More tools > Developer toolsを選択するか、Ctrl + Shift + Iを押します。 開発者ツールが表示されたら、**Sourceタブ**をクリックし、次に**Content Scriptsタブ**をクリックします。これにより、さまざまな拡張機能から実行中のコンテンツスクリプトを観察し、実行フローを追跡するためのブレークポイントを設定できます。 ### 注入されたコンテンツスクリプト {% hint style="success" %} **コンテンツスクリプトは必須ではない**ことに注意してください。**動的にスクリプトを注入**したり、**`tabs.executeScript`**を使用してウェブページに**プログラム的に注入**することも可能です。これにより、より**細かい制御**が可能になります。 {% endhint %} コンテンツスクリプトをプログラム的に注入するには、スクリプトを注入するページに対して[ホスト権限](https://developer.chrome.com/docs/extensions/reference/permissions)が必要です。これらの権限は、拡張機能のマニフェスト内でそれらを要求するか、[**activeTab**](https://developer.chrome.com/docs/extensions/reference/manifest/activeTab)を介して一時的にセキュリティを確保することができます。 #### activeTabベースの拡張機能の例 {% code title="manifest.json" %} ```json { "name": "My extension", ... "permissions": [ "activeTab", "scripting" ], "background": { "service_worker": "background.js" }, "action": { "default_title": "Action Button" } } ``` {% endcode %} * **クリック時にJSファイルをインジェクトする:** ```javascript // content-script.js document.body.style.backgroundColor = "orange"; //service-worker.js - Inject the JS file chrome.action.onClicked.addListener((tab) => { chrome.scripting.executeScript({ target: { tabId: tab.id }, files: ["content-script.js"] }); }); ``` * **クリック時に関数を注入する**: ```javascript //service-worker.js - Inject a function function injectedFunction() { document.body.style.backgroundColor = "orange"; } chrome.action.onClicked.addListener((tab) => { chrome.scripting.executeScript({ target : {tabId : tab.id}, func : injectedFunction, }); }); ``` #### スクリプト権限の例 ```javascript // service-workser.js chrome.scripting.registerContentScripts([{ id : "test", matches : [ "https://*.example.com/*" ], excludeMatches : [ "*://*/*business*" ], js : [ "contentScript.js" ], }]); // Another example chrome.tabs.executeScript(tabId, { file: "content_script.js" }); ``` ### Content Scripts `run_at` `run_at`フィールドは、**JavaScriptファイルがWebページに注入されるタイミング**を制御します。推奨されるデフォルト値は`"document_idle"`です。 可能な値は次のとおりです: - **`document_idle`**:可能な限り - **`document_start`**:`css`からのファイルの後、ただし他のDOMが構築される前や他のスクリプトが実行される前に - **`document_end`**:DOMが完全になった直後、ただし画像やフレームなどのサブリソースが読み込まれる前 #### `manifest.json`を介して ```json { "name": "My extension", ... "content_scripts": [ { "matches": ["https://*.example.com/*"], "run_at": "document_idle", "js": ["contentScript.js"] } ], ... } ``` **`service-worker.js`**を介して ```javascript chrome.scripting.registerContentScripts([{ id : "test", matches : [ "https://*.example.com/*" ], runAt : "document_idle", js : [ "contentScript.js" ], }]); ``` ### `バックグラウンド` コンテンツスクリプトによって送信されるメッセージは、**バックグラウンドページ**によって受信され、拡張機能のコンポーネントを調整する中心的な役割を果たします。特筆すべきは、バックグラウンドページが拡張機能の寿命を通じて持続し、直接的なユーザーとのやり取りなしに静かに動作します。独自のDocument Object Model(DOM)を持ち、複雑な相互作用や状態管理を可能にします。 **主なポイント**: - **バックグラウンドページの役割:** 拡張機能の中で通信と調整を確実にする神経中枢として機能します。 - **持続性:** ユーザーには見えないが、拡張機能の機能性には不可欠な、常に存在するエンティティです。 - **自動生成:** 明示的に定義されていない場合、ブラウザは自動的にバックグラウンドページを作成します。この自動生成されたページには、拡張機能のマニフェストで指定されたすべてのバックグラウンドスクリプトが含まれ、拡張機能のバックグラウンドタスクのシームレスな動作を保証します。 {% hint style="success" %} ブラウザがバックグラウンドページを自動的に生成することで(明示的に宣言されていない場合)、必要なすべてのバックグラウンドスクリプトが統合され、操作されることで、拡張機能のセットアッププロセスが合理化されます。 {% endhint %} 例:バックグラウンドスクリプト: ```js chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (request == "explain") { chrome.tabs.create({ url: "https://example.net/explanation" }); } }) ``` [ランタイム.onMessage API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)を使用してメッセージを受信します。 `"explain"`メッセージを受信すると、[tabs API](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs)を使用して新しいタブでページを開きます。 バックグラウンドスクリプトのデバッグには、**拡張機能の詳細を表示してサービスワーカーを検査**することができます。これにより、バックグラウンドスクリプトが表示された開発者ツールが開きます:
### オプションページおよびその他 ブラウザ拡張機能にはさまざまな種類のページが含まれます: * **アクションページ**は、拡張機能アイコンをクリックすると**ドロップダウンで表示**されます。 * 拡張機能が**新しいタブで読み込むページ**。 * **オプションページ**:このページは、クリックすると拡張機能の上に表示されます。前のマニフェストでは、`chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca`でこのページにアクセスできました。または、以下をクリックしてください:
これらのページは、バックグラウンドページのように永続的ではなく、必要に応じて動的にコンテンツを読み込みます。しかし、これらのページはバックグラウンドページと同様の機能を共有しています: - **コンテンツスクリプトとの通信:** バックグラウンドページと同様に、これらのページはコンテンツスクリプトからメッセージを受信し、拡張機能内での相互作用を容易にします。 - **拡張機能固有のAPIへのアクセス:** これらのページは、拡張機能固有のAPIに包括的にアクセスでき、拡張機能に定義された権限に従います。 ### `permissions`および`host_permissions` **`permissions`**および**`host_permissions`**は、ブラウザ拡張機能が持つ**どの権限**(ストレージ、位置情報など)と**どのWebページ**に対して権限を持つかを示す`manifest.json`からのエントリです。 ブラウザ拡張機能は非常に**特権的**であるため、悪意のある拡張機能や侵害された拡張機能は、攻撃者に**機密情報を盗み出したりユーザーを監視するための異なる手段を提供**する可能性があります。 これらの設定がどのように機能し、どのように悪用される可能性があるかを確認してください: {% content-ref url="browext-permissions-and-host_permissions.md" %} [browext-permissions-and-host\_permissions.md](browext-permissions-and-host\_permissions.md) {% endcontent-ref %} ### `content_security_policy` **コンテンツセキュリティポリシー**は`manifest.json`内にも宣言できます。定義されている場合、**脆弱**になる可能性があります。 ブラウザ拡張機能ページのデフォルト設定はかなり制限的です: ```bash script-src 'self'; object-src 'self'; ``` CSPとバイパスの可能性についての詳細は、以下を参照してください: {% content-ref url="../content-security-policy-csp-bypass/" %} [content-security-policy-csp-bypass](../content-security-policy-csp-bypass/) {% endcontent-ref %} ### `web_accessible_resources` ウェブページがブラウザ拡張機能のページ(たとえば`.html`ページ)にアクセスするためには、このページを`manifest.json`の**`web_accessible_resources`**フィールドに記載する必要があります。\ 例: ```javascript { ... "web_accessible_resources": [ { "resources": [ "images/*.png" ], "matches": [ "https://example.com/*" ] }, { "resources": [ "fonts/*.woff" ], "matches": [ "https://example.com/*" ] } ], ... } ``` これらのページは次のようなURLでアクセスできます: ``` chrome-extension:///message.html ``` 公開拡張機能では、**extension-id がアクセス可能**です:
ただし、`manifest.json` パラメータ **`use_dynamic_url`** が使用されている場合、この **id は動的になる**可能性があります。 これらのページにアクセスできることで、これらのページは **潜在的に ClickJacking の脆弱性**を持つ可能性があります: {% content-ref url="browext-clickjacking.md" %} [browext-clickjacking.md](browext-clickjacking.md) {% endcontent-ref %} {% hint style="success" %} これらのページがランダムな URL ではなく拡張機能のみによって読み込まれるようにすると、ClickJacking 攻撃を防ぐことができます。 {% endhint %} ### `externally_connectable` [**ドキュメント**](https://developer.chrome.com/docs/extensions/reference/manifest/externally-connectable)によると、`"externally_connectable"` マニフェスト プロパティは、[runtime.connect](https://developer.chrome.com/docs/extensions/reference/runtime#method-connect) および [runtime.sendMessage](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) を介して拡張機能に接続できる **どの拡張機能と Web ページが接続できるか** を宣言します。 * 拡張機能のマニフェストに **`externally_connectable`** キーが宣言されていないか、**`"ids": ["*"]`** として宣言されている場合、**すべての拡張機能が接続できますが、Web ページは接続できません**。 * `"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]` のように **特定の ID が指定**されている場合、**それらのアプリケーションのみ**が接続できます。 * 一致が指定されている場合、これらの Web アプリケーションが接続できます: ```json "matches": [ "https://*.google.com/*", "*://*.chromium.org/*", ``` * もし**`"externally_connectable": {}`**として指定されている場合、どのアプリやウェブサイトも接続できません。 ここで指定されている**拡張機能やURLが少ないほど**、攻撃面が**小さく**なります。 {% hint style="danger" %} もし**`externally_connectable`**で**XSSや接収に脆弱な**ウェブページが指定されている場合、攻撃者は**バックグラウンドスクリプトに直接メッセージを送信**することができ、Content ScriptとそのCSPを完全にバイパスできます。 したがって、これは**非常に強力なバイパス**です。 {% endhint %} ## ウェブ **↔︎** Content Scriptの通信 **コンテンツスクリプト**が動作する環境とホストページが存在する環境はお互いに**分離**されており、**隔離**が保たれています。 この隔離にもかかわらず、両者はページの**Document Object Model (DOM)**、共有リソースに対して相互作用する能力を持っています。 ホストページが**コンテンツスクリプト**と通信したり、コンテンツスクリプトを介して拡張機能と間接的に通信するためには、両者がアクセス可能な**DOM**を通信チャネルとして利用する必要があります。 ### ポストメッセージ {% code title="content-script.js" %} ```javascript var port = chrome.runtime.connect(); window.addEventListener("message", (event) => { // We only accept messages from ourselves if (event.source !== window) { return; } if (event.data.type && (event.data.type === "FROM_PAGE")) { console.log("Content script received: " + event.data.text); port.postMessage(event.data.text); } }, false); ``` {% endcode %} {% code title="example.js" %} ```javascript document.getElementById("theButton").addEventListener("click", () => { window.postMessage( {type : "FROM_PAGE", text : "Hello from the webpage!"}, "*"); }, false); ``` {% endcode %} セキュアなPost Message通信は、受信したメッセージの信頼性を確認する必要があります。これは以下の方法で行うことができます: - **`event.isTrusted`**: この値は、イベントがユーザーのアクションによってトリガーされた場合にのみTrueです。 - コンテンツスクリプトは、ユーザーが特定のアクションを実行した場合にのみメッセージを期待するかもしれません。 - **オリジンドメイン**: メッセージを期待するのは特定のドメインのみかもしれません。 - 正規表現を使用する場合は非常に注意してください。 - **ソース**: `received_message.source !== window` は、Content Scriptがリスニングしている**同じウィンドウからのメッセージ**かどうかをチェックするために使用できます。 前述のチェックは、実行されていても脆弱性がある可能性があるため、次のページで**潜在的なPost Messageバイパス**をチェックしてください: {% content-ref url="../postmessage-vulnerabilities/" %} [postmessage-vulnerabilities](../postmessage-vulnerabilities/) {% endcontent-ref %} ### Iframe もう1つの通信方法は**Iframe URL**を介したものです。例は以下で見つけることができます: {% content-ref url="browext-xss-example.md" %} [browext-xss-example.md](browext-xss-example.md) {% endcontent-ref %} ### DOM これは厳密には通信方法ではありませんが、**webとコンテンツスクリプトはweb DOMにアクセス**できます。したがって、**コンテンツスクリプト**がそれから情報を読み取っている場合、**web DOMを信頼**している場合、webはそのデータを**変更**できる可能性があります(webは信頼できないため、またはXSSの脆弱性があるため)そして**Content Scriptを危険にさらす**可能性があります。 **ブラウザ拡張機能を危険にさらすDOMベースのXSSの例**も以下で見つけることができます: {% content-ref url="browext-xss-example.md" %} [browext-xss-example.md](browext-xss-example.md) {% endcontent-ref %} ## メモリ/コード内の機密情報 ブラウザ拡張機能が**メモリ内に機密情報を保存**している場合、これは(特にWindowsマシンで)**ダンプ**され、この情報を**検索**する可能性があります。 したがって、ブラウザ拡張機能のメモリは**安全ではない**と見なすべきであり、資格情報やニーモニックフレーズなどの**機密情報は保存されてはいけません**。 もちろん、**コード内に機密情報を入れない**でください。それは**公開**されることになります。 ## Content Script **↔︎** Background Script Communication Content Scriptは、[**runtime.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/runtime#method-sendMessage) **または** [**tabs.sendMessage()**](https://developer.chrome.com/docs/extensions/reference/tabs#method-sendMessage) 関数を使用して**ワンタイムのJSONシリアライズ可能な**メッセージを送信できます。 **応答**を処理するには、返された**Promise**を使用します。ただし、後方互換性のために、最後の引数として**コールバック**を渡すこともできます。 **コンテンツスクリプト**からリクエストを送信する方法は次のようになります: ```javascript (async () => { const response = await chrome.runtime.sendMessage({greeting: "hello"}); // do something with response here, not outside the function console.log(response); })(); ``` **拡張機能**(通常は**バックグラウンドスクリプト**)からリクエストを送信します。コンテンツスクリプトは、指定したタブに送信する必要があります。選択したタブのコンテンツスクリプトにメッセージを送信する方法の例: ```javascript // From https://stackoverflow.com/questions/36153999/how-to-send-a-message-between-chrome-extension-popup-and-content-script (async () => { const [tab] = await chrome.tabs.query({active: true, lastFocusedWindow: true}); const response = await chrome.tabs.sendMessage(tab.id, {greeting: "hello"}); // do something with response here, not outside the function console.log(response); })(); ``` **受信側**では、メッセージを処理するために[**runtime.onMessage**](https://developer.chrome.com/docs/extensions/reference/runtime#event-onMessage) **イベントリスナー**を設定する必要があります。これはコンテンツスクリプトや拡張機能ページから見ても同じように見えます。 ```javascript // From https://stackoverflow.com/questions/70406787/javascript-send-message-from-content-js-to-background-js chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { console.log(sender.tab ? "from a content script:" + sender.tab.url : "from the extension"); if (request.greeting === "hello") sendResponse({farewell: "goodbye"}); } ); ``` 例で強調されているように、**`sendResponse()`** は同期的に実行されました。`sendResponse()` を非同期に実行するために `onMessage` イベントハンドラを変更するには、`return true;` を組み込むことが重要です。 重要な考慮事項として、複数のページが `onMessage` イベントを受信するシナリオでは、特定のイベントに対して最初に `sendResponse()` を実行するページだけが効果的に応答を配信できます。同じイベントへの後続の応答は考慮されません。 新しい拡張機能を作成する際は、コールバックではなくプロミスを使用することが好ましいです。コールバックの使用に関しては、`sendResponse()` 関数は、同期的なコンテキスト内で直接実行される場合、またはイベントハンドラが非同期操作を示すために `true` を返す場合にのみ有効と見なされます。ハンドラがどれも `true` を返さない場合や、`sendResponse()` 関数がメモリから削除される(ガベージコレクトされる)と、`sendMessage()` 関数に関連付けられたコールバックがデフォルトでトリガーされます。 ## ブラウザでの拡張機能の読み込み 1. ブラウザ拡張機能を**ダウンロード**して解凍します 2. **`chrome://extensions/`** に移動し、`開発者モード` を**有効**にします 3. **`アンパックされた拡張機能を読み込む`** ボタンをクリックします **Firefox** の場合は、**`about:debugging#/runtime/this-firefox`** に移動し、**`一時的なアドオンを読み込む`** ボタンをクリックします。 ## ストアからソースコードを取得 Chrome 拡張機能のソースコードはさまざまな方法で取得できます。以下に各オプションの詳細な説明と手順を示します。 ### コマンドラインを使用して ZIP 形式で拡張機能をダウンロード Chrome 拡張機能のソースコードは、コマンドラインを使用して ZIP ファイルとしてダウンロードできます。これには、`curl` を使用して特定の URL から ZIP ファイルを取得し、その後 ZIP ファイルの内容をディレクトリに展開する必要があります。以下に手順を示します: 1. `"extension_id"` を実際の拡張機能の ID に置き換えます。 2. 次のコマンドを実行します: ```bash extension_id=your_extension_id # Replace with the actual extension ID curl -L -o "$extension_id.zip" "https://clients2.google.com/service/update2/crx?response=redirect&os=mac&arch=x86-64&nacl_arch=x86-64&prod=chromecrx&prodchannel=stable&prodversion=44.0.2403.130&x=id%3D$extension_id%26uc" unzip -d "$extension_id-source" "$extension_id.zip" ``` ### CRX Viewerウェブサイトを使用する [https://robwu.nl/crxviewer/](https://robwu.nl/crxviewer/) ### CRX Viewer拡張機能を使用する もう1つの便利な方法は、オープンソースプロジェクトであるChrome Extension Source Viewerを使用することです。[Chrome Web Store](https://chrome.google.com/webstore/detail/chrome-extension-source-v/jifpbeccnghkjeaalbbjmodiffmgedin?hl=en)からインストールできます。ビューアのソースコードは、[GitHubリポジトリ](https://github.com/Rob--W/crxviewer)で入手できます。 ### ローカルにインストールされた拡張機能のソースを表示する ローカルにインストールされたChrome拡張機能も検査できます。以下の方法で行います: 1. `chrome://version/`にアクセスし、"Profile Path"フィールドを見つけてChromeのローカルプロファイルディレクトリにアクセスします。 2. プロファイルディレクトリ内の`Extensions/`サブフォルダに移動します。 3. このフォルダには、通常、読みやすい形式でソースコードが含まれているすべてのインストールされた拡張機能が含まれています。 拡張機能を識別するために、それらのIDを名前にマッピングできます: - `about:extensions`ページで開発者モードを有効にして、各拡張機能のIDを表示します。 - 各拡張機能のフォルダ内にある`manifest.json`ファイルには、拡張機能を識別するのに役立つ読みやすい`name`フィールドが含まれています。 ### ファイルアーカイバまたはアンパッカーを使用する Chrome Web Storeに移動して、拡張機能をダウンロードします。ファイルの拡張子は`.crx`になります。 ファイルの拡張子を`.zip`に変更します。 WinRAR、7-Zipなどのファイルアーカイバを使用して、ZIPファイルの内容を抽出します。 ### Chromeの開発者モードを使用する Chromeを開いて`chrome://extensions/`に移動します。 右上の「開発者モード」を有効にします。 「パッケージ化されていない拡張機能を読み込む」をクリックします。 拡張機能のディレクトリに移動します。 これによりソースコードはダウンロードされませんが、すでにダウンロードされたり開発された拡張機能のコードを表示および変更するのに便利です。 ## セキュリティ監査チェックリスト ブラウザ拡張機能は**攻撃面が限られています**が、一部には**脆弱性**や**強化の余地**がある場合があります。以下は最も一般的なものです: * [ ] 要求される**`permissions`**を可能な限り**制限**する * [ ] 可能な限り**`host_permissions`**を**制限**する * [ ] **強力な** **`content_security_policy`**を使用する * [ ] 必要がない場合は**`externally_connectable`**を可能な限り**制限**し、デフォルトで残さずに**`{}`**を指定する * [ ] ここでXSSや乗っ取りに**脆弱なURL**が言及されている場合、攻撃者は**バックグラウンドスクリプトに直接メッセージを送信**できます。非常に強力なバイパスです。 * [ ] 可能な限り**`web_accessible_resources`**を制限し、可能であれば空にしてください。 * [ ] もし**`web_accessible_resources`**がない場合は、[**ClickJacking**](browext-clickjacking.md)をチェックしてください * [ ] 拡張機能からウェブページへの**通信**が発生する場合、通信によって引き起こされる[XSS**脆弱性**](browext-xss-example.md)をチェックしてください。 * [ ] Post Messagesが使用されている場合は、[**Post Messageの脆弱性**](../postmessage-vulnerabilities/)をチェックしてください。 * [ ] **Content ScriptがDOMの詳細にアクセス**する場合は、それらがWebによって**変更**された場合にXSSを導入していないかを確認してください * [ ] この通信が**Content Script -> Background script通信**にも関与している場合は特に注意してください * ブラウザ拡張機能の中に**機密情報を保存**すべきではありません * ブラウザ拡張機能の中に**機密情報を保存**すべきではありません ## ツール ### [**Tarnish**](https://thehackerblog.com/tarnish/) * 提供されたChrome Webstoreリンクから任意のChrome拡張機能を取得します。 * [**manifest.json**](https://developer.chrome.com/extensions/manifest) **ビューア**:拡張機能のマニフェストのJSON整形バージョンを簡単に表示します。 * **フィンガープリント解析**:[web\_accessible\_resources](https://developer.chrome.com/extensions/manifest/web\_accessible\_resources)の検出およびChrome拡張機能のフィンガープリントJavaScriptの自動生成。 * **潜在的なClickjacking解析**:[web\_accessible\_resources](https://developer.chrome.com/extensions/manifest/web\_accessible\_resources)ディレクティブが設定された拡張機能HTMLページの検出。これらはページの目的に応じてClickjackingの脆弱性があります。 * **許可警告ビューア**:ユーザーが拡張機能をインストールしようとすると表示されるすべてのChrome許可プロンプト警告のリストを表示します。 * **危険な機能**:攻撃者によって悪用される可能性のある危険な機能の場所を表示します(例:innerHTML、chrome.tabs.executeScriptなどの機能)。 * **エントリーポイント**:拡張機能がユーザー/外部入力を受け入れる場所を表示します。これは拡張機能の表面積を理解し、悪意のあるデータを拡張機能に送信する潜在的なポイントを探すのに役立ちます。 * 危険な機能とエントリーポイントのスキャナーは、生成されたアラートに次のものを持っています: * アラートを引き起こした関連するコードスニペットと行。 * 問題の説明。 * アラートを引き起こしたファイル全体を表示するための「ファイルを表示」ボタン。 * アラートされたファイルのパス。 * アラートされたファイルの完全なChrome拡張機能URI。 * JavaScriptファイル内の脆弱な行が含まれている場合、それが含まれているすべてのページのパスと、これらのページのタイプ、[web\_accessible\_resource](https://developer.chrome.com/extensions/manifest/web\_accessible\_resources)のステータス。 * **コンテンツセキュリティポリシー(CSP)アナライザーおよびバイパスチェッカー**:拡張機能のCSPの弱点を指摘し、ホワイトリストによるCSPのバイパス方法を明らかにします。 * **既知の脆弱なライブラリ**:[Retire.js](https://retirejs.github.io/retire.js/)を使用して既知の脆弱なJavaScriptライブラリの使用をチェックします。 * 拡張機能とフォーマットされたバージョンをダウンロードします。 * オリジナルの拡張機能をダウンロードします。 * 拡張機能の美しく整形されたバージョンをダウンロードします(自動整形されたHTMLおよびJavaScript)。 * スキャン結果の自動キャッシュ化。拡張機能のスキャンを実行すると、最初の実行ではかなりの時間がかかりますが、2回目以降は、拡張機能が更新されていない限り、結果がキャッシュされているためほぼ即座になります。 * リンク可能なレポートURL、Tarnishによって生成された拡張機能レポートへのリンクを簡単に他の人にリンクできます。 ### [Neto](https://github.com/elevenpaths/neto) Project Netoは、FirefoxやChromeなどのよく知られたブラウザ用のプラグインや拡張機能の隠れた機能を分析し解明するために設計されたPython 3パッケージです。このパッケージは、パッケージ化されたファイルを解凍して、`manifest.json`、ローカライゼーションフォルダ、JavaScriptおよびHTMLソースファイルからこれらの機能を抽出するプロセスを自動化します。 ## 参考文献 * この方法論の支援に感謝します[**@naivenom**](https://twitter.com/naivenom) * [https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing](https://www.cobalt.io/blog/introduction-to-chrome-browser-extension-security-testing) * [https://palant.info/2022/08/10/anatomy-of-a-basic-extension/](https://palant.info/2022/08/10/anatomy-of-a-basic-extension/) * [https://palant.info/2022/08/24/attack-surface-of-extension-pages/](https://palant.info/2022/08/24/attack-surface-of-extension-pages/) * [https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/](https://palant.info/2022/08/31/when-extension-pages-are-web-accessible/) * [https://help.passbolt.com/assets/files/PBL-02-report.pdf](https://help.passbolt.com/assets/files/PBL-02-report.pdf) * [https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts](https://developer.chrome.com/docs/extensions/develop/concepts/content-scripts) * [https://developer.chrome.com/docs/extensions/mv2/background-pages](https://developer.chrome.com/docs/extensions/mv2/background-pages) * [https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/](https://thehackerblog.com/kicking-the-rims-a-guide-for-securely-writing-and-auditing-chrome-extensions/) * [https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0](https://gist.github.com/LongJohnCoder/9ddf5735df3a4f2e9559665fb864eac0)