Browser Extension Pentesting Methodology
基本情報
ブラウザ拡張機能はJavaScriptで書かれ、ブラウザによってバックグラウンドで読み込まれます。拡張機能は独自のDOMを持っていますが、他のサイトのDOMと相互作用することができます。これは、他のサイトの機密性、完全性、および可用性(CIA)を危険にさらす可能性があることを意味します。
主なコンポーネント
拡張機能のレイアウトは視覚化されると最も良く見え、3つのコンポーネントで構成されています。それぞれのコンポーネントを詳しく見ていきましょう。
コンテンツスクリプト
各コンテンツスクリプトは単一のウェブページのDOMに直接アクセスでき、潜在的に悪意のある入力にさらされます。しかし、コンテンツスクリプトは拡張機能のコアにメッセージを送信する能力以外の権限を持っていません。
拡張機能コア
拡張機能コアは、ほとんどの拡張機能の特権/アクセスを含んでいますが、拡張機能コアはXMLHttpRequestおよびコンテンツスクリプトを介してのみウェブコンテンツと相互作用できます。また、拡張機能コアはホストマシンに直接アクセスすることはできません。
ネイティブバイナリ
拡張機能は、ユーザーの完全な権限でホストマシンにアクセスできるネイティブバイナリを許可します。ネイティブバイナリは、Flashや他のブラウザプラグインで使用される標準のNetscapeプラグインアプリケーションプログラミングインターフェース(NPAPI)を介して拡張機能コアと相互作用します。
境界
ユーザーの完全な権限を取得するには、攻撃者は拡張機能に悪意のある入力をコンテンツスクリプトから拡張機能のコアに、そして拡張機能のコアからネイティブバイナリに渡すように説得しなければなりません。
拡張機能の各コンポーネントは、強力な保護境界によって互いに分離されています。各コンポーネントは別々のオペレーティングシステムプロセスで実行されます。コンテンツスクリプトと拡張機能コアは、ほとんどのオペレーティングシステムサービスに利用できないサンドボックスプロセスで実行されます。
さらに、コンテンツスクリプトは別のJavaScriptヒープで実行されることによって、関連するウェブページから分離されています。コンテンツスクリプトとウェブページは同じ基盤となるDOMにアクセスできますが、2つはJavaScriptポインタを交換することは決してありません。これにより、JavaScript機能の漏洩を防ぎます。
manifest.json
manifest.json
Chrome拡張機能は、単に.crxファイル拡張子を持つZIPフォルダーです。拡張機能のコアは、フォルダーのルートにある**manifest.json
**ファイルで、レイアウト、権限、およびその他の設定オプションを指定します。
Example:
content_scripts
content_scripts
コンテンツスクリプトは、ユーザーが一致するページに移動するたびに読み込まれ、この場合は**https://example.com/*
** 表現に一致する任意のページであり、*://*/*/business*
正規表現に一致しないページです。これらはページ自身のスクリプトのように実行され、ページのDocument Object Model (DOM)に対して任意のアクセス権を持っています。
より多くのURLを含めたり除外したりするために、include_globs
と exclude_globs
を使用することも可能です。
これは、ストレージAPI を使用して拡張機能のストレージから message
値を取得し、ページに説明ボタンを追加する例のコンテンツスクリプトです。
このボタンがクリックされると、コンテンツスクリプトによって拡張ページにメッセージが送信されます。これは、runtime.sendMessage() APIを利用するためです。コンテンツスクリプトはAPIへの直接アクセスに制限があり、storage
が数少ない例外の一つです。これらの例外を超える機能については、メッセージが拡張ページに送信され、コンテンツスクリプトが通信できるようになります。
ブラウザによって、コンテンツスクリプトの機能は若干異なる場合があります。Chromiumベースのブラウザの場合、機能リストはChrome Developers documentationで入手可能で、Firefoxの場合はMDNが主な情報源となります。 また、コンテンツスクリプトはバックグラウンドスクリプトと通信する能力があり、これによりアクションを実行し、応答を返すことができます。
Chromeでコンテンツスクリプトを表示およびデバッグするには、オプション > その他のツール > デベロッパーツールからChromeデベロッパーツールメニューにアクセスするか、Ctrl + Shift + Iを押します。
デベロッパーツールが表示されたら、ソースタブをクリックし、次にコンテンツスクリプトタブをクリックします。これにより、さまざまな拡張機能から実行中のコンテンツスクリプトを観察し、実行フローを追跡するためのブレークポイントを設定できます。
注入されたコンテンツスクリプト
コンテンツスクリプトは必須ではないことに注意してください。動的にスクリプトを注入したり、プログラム的に注入することも可能です。これは実際により詳細な制御を提供します。
コンテンツスクリプトをプログラム的に注入するには、拡張機能がスクリプトを注入するページに対してホスト権限を持っている必要があります。これらの権限は、拡張機能のマニフェスト内で要求するか、activeTabを通じて一時的に取得することができます。
activeTabベースの拡張機能の例
クリックでJSファイルをインジェクトする:
クリック時に関数を注入する:
スクリプト権限の例
より多くのURLを含めたり除外したりするために、include_globs
と exclude_globs
を使用することも可能です。
コンテンツスクリプト run_at
run_at
run_at
フィールドは JavaScriptファイルがウェブページに注入されるタイミング を制御します。推奨されるデフォルト値は "document_idle"
です。
可能な値は次のとおりです:
document_idle
: 可能な限りdocument_start
:css
からのファイルの後、しかし他のDOMが構築される前や他のスクリプトが実行される前。document_end
: DOMが完了した直後ですが、画像やフレームなどのサブリソースが読み込まれる前。
manifest.json
経由
manifest.json
経由**service-worker.js
**を介して
background
background
コンテンツスクリプトによって送信されたメッセージは、バックグラウンドページによって受信され、拡張機能のコンポーネントを調整する中心的な役割を果たします。特に、バックグラウンドページは拡張機能のライフタイムを通じて持続し、直接的なユーザーの操作なしに静かに動作します。独自のドキュメントオブジェクトモデル(DOM)を持ち、複雑な相互作用と状態管理を可能にします。
重要なポイント:
バックグラウンドページの役割: 拡張機能の神経中枢として機能し、拡張機能のさまざまな部分間の通信と調整を確保します。
持続性: ユーザーには見えないが、拡張機能の機能に不可欠な常に存在するエンティティです。
自動生成: 明示的に定義されていない場合、ブラウザは自動的にバックグラウンドページを作成します。この自動生成されたページには、拡張機能のマニフェストに指定されたすべてのバックグラウンドスクリプトが含まれ、拡張機能のバックグラウンドタスクのシームレスな操作を確保します。
明示的に宣言されていない場合にブラウザがバックグラウンドページを自動生成することによって提供される便利さは、すべての必要なバックグラウンドスクリプトが統合され、機能することを保証し、拡張機能のセットアッププロセスを簡素化します。
Example background script:
それは、runtime.onMessage APIを使用してメッセージをリッスンします。"explain"
メッセージを受信すると、tabs APIを使用して新しいタブでページを開きます。
バックグラウンドスクリプトをデバッグするには、拡張機能の詳細に移動してサービスワーカーを検査することができます。これにより、バックグラウンドスクリプトを含む開発者ツールが開きます:
オプションページとその他
ブラウザ拡張機能にはさまざまな種類のページが含まれることがあります:
アクションページは、拡張機能のアイコンがクリックされたときにドロップダウンに表示されます。
拡張機能が新しいタブで読み込むページ。
オプションページ:このページは、クリックすると拡張機能の上に表示されます。前のマニフェストでは、
chrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
でこのページにアクセスできました。または、クリックすることで:
これらのページは、必要に応じて動的にコンテンツを読み込むため、バックグラウンドページのように永続的ではないことに注意してください。それにもかかわらず、これらはバックグラウンドページと特定の機能を共有します:
コンテンツスクリプトとの通信:バックグラウンドページと同様に、これらのページはコンテンツスクリプトからメッセージを受信でき、拡張機能内での相互作用を促進します。
拡張機能固有のAPIへのアクセス:これらのページは、拡張機能に定義された権限に従って、拡張機能固有のAPIへの包括的なアクセスを享受します。
permissions
& host_permissions
permissions
& host_permissions
**permissions
とhost_permissions
**は、manifest.json
のエントリで、ブラウザ拡張機能がどの権限(ストレージ、位置情報など)を持っているか、どのウェブページであるかを示します。
ブラウザ拡張機能は非常に特権的であるため、悪意のあるものや侵害されたものは、攻撃者に機密情報を盗んだり、ユーザーを監視したりするためのさまざまな手段を提供する可能性があります。
これらの設定がどのように機能し、どのように悪用される可能性があるかを確認してください:
BrowExt - permissions & host_permissionscontent_security_policy
content_security_policy
コンテンツセキュリティポリシーは、manifest.json
内にも宣言できます。定義されている場合、それは脆弱である可能性があります。
ブラウザ拡張機能ページのデフォルト設定はかなり制限されています:
CSPおよび潜在的なバイパスに関する詳細は、以下を確認してください:
Content Security Policy (CSP) Bypassweb_accessible_resources
web_accessible_resources
ウェブページがブラウザ拡張のページにアクセスするためには、例えば.html
ページ、このページはmanifest.json
の**web_accessible_resources
**フィールドに記載されている必要があります。
例えば:
これらのページは、次のようなURLでアクセス可能です:
公共拡張機能では、extension-idがアクセス可能です:
ただし、manifest.json
パラメータ**use_dynamic_url
が使用されている場合、このidは動的**になる可能性があります。
ここにページが記載されていても、Content Security PolicyのおかげでClickJackingに対して保護されている可能性があることに注意してください。したがって、ClickJacking攻撃が可能であることを確認する前に、これを(frame-ancestorsセクション)チェックする必要があります。
これらのページにアクセスできることは、これらのページが潜在的に脆弱なClickJackingであることを意味します:
BrowExt - ClickJackingこれらのページが拡張機能によってのみ読み込まれ、ランダムなURLからは読み込まれないようにすることで、ClickJacking攻撃を防ぐことができます。
web_accessible_resources
からのページや拡張機能の他のページもバックグラウンドスクリプトに連絡することができることに注意してください。したがって、これらのページのいずれかがXSSに対して脆弱である場合、より大きな脆弱性を引き起こす可能性があります。
さらに、**web_accessible_resources
に示されたページはiframe内でのみ開くことができますが、新しいタブからは拡張機能IDを知っていれば拡張機能内の任意のページにアクセスすることが可能です。したがって、同じパラメータを悪用するXSSが見つかった場合、ページがweb_accessible_resources
**に設定されていなくても悪用される可能性があります。
externally_connectable
externally_connectable
docsによると、"externally_connectable"
マニフェストプロパティは、どの拡張機能とウェブページがあなたの拡張機能に接続できるかを宣言します。これはruntime.connectおよびruntime.sendMessageを介して行われます。
externally_connectable
キーが拡張機能のマニフェストに宣言されていない場合、または**"ids": ["*"]
**として宣言されている場合、すべての拡張機能が接続できますが、ウェブページは接続できません。特定のIDが指定されている場合、例えば
"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
のように、そのアプリケーションのみが接続できます。matchesが指定されている場合、これらのウェブアプリは接続できるようになります:
空として指定されている場合:
"externally_connectable": {}
、アプリやウェブは接続できません。
ここで示されている 拡張機能とURLが少ないほど、攻撃面が小さくなります。
もしウェブページが externally_connectable
に XSSまたはテイクオーバーに脆弱 として示されている場合、攻撃者は バックグラウンドスクリプトに直接メッセージを送信 でき、コンテンツスクリプトとそのCSPを完全にバイパスすることができます。
したがって、これは 非常に強力なバイパス です。
さらに、クライアントが不正な拡張機能をインストールした場合、たとえそれが脆弱な拡張機能と通信することが許可されていなくても、許可されたウェブページにXSSデータを注入 したり、WebRequest
または DeclarativeNetRequest
APIを悪用して、ターゲットドメインのリクエストを操作し、JavaScriptファイルのリクエストを変更することができます。(ターゲットページのCSPがこれらの攻撃を防ぐ可能性があることに注意してください)。このアイデアは この書き込みから 来ています。
コミュニケーションの概要
拡張機能 <--> ウェブアプリ
コンテンツスクリプトとウェブページ間で通信するために、通常はポストメッセージが使用されます。したがって、ウェブアプリケーションでは通常 window.postMessage
関数への呼び出しが見られ、コンテンツスクリプトでは window.addEventListener
のようなリスナーが見られます。ただし、拡張機能は ポストメッセージを送信してウェブアプリケーションと通信 することもできるため、ウェブはそれを期待する必要があります。または、ウェブに新しいスクリプトを読み込ませることもできます。
拡張機能内
通常、chrome.runtime.sendMessage
関数が拡張機能内でメッセージを送信するために使用され(通常は background
スクリプトによって処理されます)、それを受信して処理するためにリスナーが chrome.runtime.onMessage.addListener
を呼び出して宣言されます。
chrome.runtime.connect()
を使用して、単一のメッセージを送信する代わりに持続的な接続を持つことも可能で、次の例のように メッセージを送信 および 受信 するために使用できます。
Last updated