基本情報
ブラウザ拡張機能はJavaScriptで書かれ、ブラウザによってバックグラウンドで読み込まれます。独自のDOM を持っていますが、他のサイトのDOMと相互作用することができます。これは、他のサイトの機密性、完全性、および可用性(CIA)を危険にさらす可能性があることを意味します。
主なコンポーネント
拡張機能のレイアウトは視覚化されると最も良く見え、3つのコンポーネントで構成されています。それぞれのコンポーネントを詳しく見ていきましょう。
コンテンツスクリプト
各コンテンツスクリプトは単一のウェブページ のDOMに直接アクセスでき、潜在的に悪意のある入力 にさらされます。ただし、コンテンツスクリプトは拡張機能のコアにメッセージを送信する能力以外の権限を持っていません。
拡張機能コア
拡張機能コアは、ほとんどの拡張機能の特権/アクセスを含んでいますが、拡張機能コアはXMLHttpRequest およびコンテンツスクリプトを介してのみウェブコンテンツと相互作用できます。また、拡張機能コアはホストマシンに直接アクセスすることはできません。
ネイティブバイナリ
拡張機能は、ユーザーの完全な権限でホストマシンにアクセスできるネイティブバイナリ を許可します。ネイティブバイナリは、Flashや他のブラウザプラグインで使用される標準のNetscapeプラグインAPI(NPAPI )を介して拡張機能コアと相互作用します。
境界
ユーザーの完全な権限を取得するには、攻撃者は拡張機能に悪意のある入力をコンテンツスクリプトから拡張機能のコアに、そして拡張機能のコアからネイティブバイナリに渡すように説得しなければなりません。
拡張機能の各コンポーネントは、強力な保護境界 によって互いに分離されています。各コンポーネントは別々のオペレーティングシステムプロセス で実行されます。コンテンツスクリプトと拡張機能コアは、ほとんどのオペレーティングシステムサービスに利用できないサンドボックスプロセス で実行されます。
さらに、コンテンツスクリプトは別のJavaScriptヒープで実行されることによって、関連するウェブページから分離されています 。コンテンツスクリプトとウェブページは同じ基盤となるDOMにアクセスできますが 、二つはJavaScriptポインタを交換することは決してありません 。これにより、JavaScript機能の漏洩を防ぎます。
manifest.json
Chrome拡張機能は、単に.crxファイル拡張子 を持つZIPフォルダーです。拡張機能のコアは、フォルダーのルートにある**manifest.json
**ファイルで、レイアウト、権限、およびその他の設定オプションを指定します。
例:
Copy {
"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) に対して任意のアクセス権を持っています。
Copy "content_scripts" : [
{
"js" : [
"script.js"
] ,
"matches" : [
"https://example.com/*" ,
"https://www.example.com/*"
] ,
"exclude_matches" : [ "*://*/*business*" ] ,
}
],
より多くのURLを含めたり除外したりするために、include_globs
と exclude_globs
を使用することも可能です。
これは、ストレージAPI を使用して拡張機能のストレージからmessage
値を取得する際に、ページに説明ボタンを追加する例のコンテンツスクリプトです。
Copy chrome . storage . local .get ( "message" , result =>
{
let div = document .createElement ( "div" );
div .innerHTML = result .message + " <button>Explain</button>" ;
div .querySelector ( "button" ) .addEventListener ( "click" , () =>
{
chrome . runtime .sendMessage ( "explain" );
});
document . body .appendChild (div);
});
このボタンがクリックされると、コンテンツスクリプトによって拡張ページにメッセージが送信されます。これは、runtime.sendMessage() API を利用するためです。コンテンツスクリプトはAPIへの直接アクセスに制限があり、storage
が数少ない例外の一つです。これらの例外を超える機能については、メッセージが拡張ページに送信され、コンテンツスクリプトが通信できるようになります。
ブラウザによって、コンテンツスクリプトの機能は若干異なる場合があります。Chromiumベースのブラウザの場合、機能リストはChrome Developers documentation で入手可能で、Firefoxの場合はMDN が主な情報源となります。
また、コンテンツスクリプトはバックグラウンドスクリプトと通信する能力があり、これによりアクションを実行し、応答を返すことができる点も注目に値します。
Chromeでコンテンツスクリプトを表示およびデバッグするには、オプション > その他のツール > デベロッパーツールからChromeデベロッパーツールメニューにアクセスするか、Ctrl + Shift + Iを押します。
デベロッパーツールが表示されたら、ソースタブ をクリックし、次にコンテンツスクリプト タブをクリックします。これにより、さまざまな拡張機能から実行中のコンテンツスクリプトを観察し、実行フローを追跡するためのブレークポイントを設定できます。
注入されたコンテンツスクリプト
コンテンツスクリプトは必須ではない ことに注意してください。動的に スクリプトを注入 したり、プログラム的に注入 することも可能です。これは実際により詳細な制御 を提供します。
コンテンツスクリプトをプログラム的に注入するには、拡張機能がスクリプトを注入するページに対してホスト権限 を持っている必要があります。これらの権限は、拡張機能のマニフェスト内で要求する か、activeTab を通じて一時的に取得することができます。
activeTabベースの拡張機能の例
Copy {
"name" : "My extension" ,
...
"permissions" : [
"activeTab" ,
"scripting"
] ,
"background" : {
"service_worker" : "background.js"
} ,
"action" : {
"default_title" : "Action Button"
}
}
Copy // 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" ]
});
});
Copy //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 ,
});
});
スクリプト権限の例
Copy // 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" });
より多くのURLを含めたり除外したりするために、include_globs
と exclude_globs
を使用することも可能です。
コンテンツスクリプト run_at
run_at
フィールドは JavaScriptファイルがウェブページに注入されるタイミング を制御します。推奨されるデフォルト値は "document_idle"
です。
可能な値は次のとおりです:
document_start
: css
からのファイルの後、しかし他のDOMが構築される前や他のスクリプトが実行される前。
document_end
: DOMが完了した直後ですが、画像やフレームなどのサブリソースが読み込まれる前。
manifest.json
を介して
Copy {
"name" : "My extension" ,
...
"content_scripts" : [
{
"matches" : [ "https://*.example.com/*" ] ,
"run_at" : "document_idle" ,
"js" : [ "contentScript.js" ]
}
] ,
...
}
Via service-worker.js
Copy chrome . scripting .registerContentScripts ([{
id : "test" ,
matches : [ "https://*.example.com/*" ] ,
runAt : "document_idle" ,
js : [ "contentScript.js" ] ,
}]);
background
コンテンツスクリプトによって送信されたメッセージは、バックグラウンドページ によって受信され、拡張機能のコンポーネントを調整する中心的な役割を果たします。特に、バックグラウンドページは拡張機能のライフタイムを通じて持続し、直接的なユーザーの操作なしに静かに動作します。独自のドキュメントオブジェクトモデル(DOM)を持ち、複雑な相互作用と状態管理を可能にします。
重要なポイント :
バックグラウンドページの役割: 拡張機能の神経中枢として機能し、拡張機能のさまざまな部分間の通信と調整を確保します。
持続性: ユーザーには見えないが、拡張機能の機能に不可欠な常に存在するエンティティです。
自動生成: 明示的に定義されていない場合、ブラウザは自動的にバックグラウンドページを作成します。この自動生成されたページには、拡張機能のマニフェストに指定されたすべてのバックグラウンドスクリプトが含まれ、拡張機能のバックグラウンドタスクのシームレスな操作を確保します。
明示的に宣言されていない場合にブラウザがバックグラウンドページを自動的に生成することによって提供される便利さは、すべての必要なバックグラウンドスクリプトが統合され、動作することを保証し、拡張機能のセットアッププロセスを簡素化します。
Example background script:
Copy chrome . runtime . onMessage .addListener ((request , sender , sendResponse) =>
{
if (request == "explain" )
{
chrome . tabs .create ({ url : "https://example.net/explanation" });
}
})
It uses runtime.onMessage API to listen to messages. When an "explain"
message is received, it uses tabs API to open a page in a new tab.
To debug the background script you could go to the extension details and inspect the service worker, this will open the developer tools with the background script:
オプションページとその他
ブラウザ拡張機能にはさまざまな種類のページが含まれることがあります:
アクションページ は、拡張機能のアイコン がクリックされたときにドロップダウンで表示されます。
オプションページ :このページはクリックすると拡張機能の上に表示されます。前のマニフェストでは、私はこのページにchrome://extensions/?options=fadlhnelkbeojnebcbkacjilhnbjfjca
でアクセスできました、またはクリックすることで:
これらのページは、必要に応じて動的にコンテンツを読み込むため、バックグラウンドページのように永続的ではないことに注意してください。それにもかかわらず、これらはバックグラウンドページと特定の機能を共有しています:
コンテンツスクリプトとの通信: バックグラウンドページと同様に、これらのページはコンテンツスクリプトからメッセージを受信でき、拡張機能内での相互作用を促進します。
拡張機能固有のAPIへのアクセス: これらのページは、拡張機能に定義された権限に従って、拡張機能固有のAPIへの包括的なアクセスを享受します。
permissions
& host_permissions
permissions
と host_permissions
は、ブラウザ拡張機能がどの権限 (ストレージ、位置情報など)を持っているか、どのウェブページ でそれを持っているかを示すmanifest.json
のエントリです。
ブラウザ拡張機能は非常に特権的 であるため、悪意のあるものや侵害されたものは、攻撃者に機密情報を盗んだり、ユーザーを監視したりするためのさまざまな手段を提供する可能性があります 。
これらの設定がどのように機能し、どのように悪用される可能性があるかを確認してください:
content_security_policy
コンテンツセキュリティポリシー は、manifest.json
内でも宣言できます。定義されている場合、それは脆弱 である可能性があります。
ブラウザ拡張機能ページのデフォルト設定はかなり制限されています:
Copy script-src 'self' ; object-src 'self' ;
CSPや潜在的なバイパスに関する詳細は、以下を確認してください:
web_accessible_resources
ウェブページがブラウザ拡張のページ、例えば.html
ページにアクセスするためには、このページがmanifest.json
の**web_accessible_resources
**フィールドに記載されている必要があります。
例えば:
Copy {
...
"web_accessible_resources" : [
{
"resources" : [ "images/*.png" ] ,
"matches" : [ "https://example.com/*" ]
} ,
{
"resources" : [ "fonts/*.woff" ] ,
"matches" : [ "https://example.com/*" ]
}
] ,
...
}
これらのページは、次のようなURLでアクセス可能です:
Copy chrome-extension://<extension-id>/message.html
公共拡張機能では、extension-idがアクセス可能 です:
ただし、manifest.json
パラメータ**use_dynamic_url
が使用されている場合、この idは動的**になる可能性があります。
ここにページが記載されていても、Content Security Policy のおかげでClickJackingから保護されている 可能性があることに注意してください。したがって、ClickJacking攻撃が可能かどうかを確認する前に、これをチェックする必要があります(frame-ancestorsセクション)。
これらのページにアクセスできることは、これらのページが潜在的に脆弱なClickJacking であることを意味します:
これらのページが拡張機能によってのみ読み込まれ、ランダムなURLからは読み込まれないようにすることで、ClickJacking攻撃を防ぐことができます。
web_accessible_resources
からのページや拡張機能の他のページもバックグラウンドスクリプトに連絡する ことができることに注意してください。したがって、これらのページのいずれかがXSS に対して脆弱である場合、より大きな脆弱性を引き起こす可能性があります。
さらに、**web_accessible_resources
に示されたページはiframe内でのみ開くことができますが、新しいタブからは拡張機能IDを知っていれば拡張機能内の任意のページにアクセスすることが可能です。したがって、同じパラメータを悪用するXSSが見つかった場合、ページが web_accessible_resources
**に設定されていなくても悪用される可能性があります。
externally_connectable
docs によると、"externally_connectable"
マニフェストプロパティは、どの拡張機能とウェブページがあなたの拡張機能に接続できるか を宣言します。これは、runtime.connect およびruntime.sendMessage を介して行われます。
externally_connectable
キーが拡張機能のマニフェストに宣言されていない 場合、または**"ids": ["*"]
**として宣言されている場合、すべての拡張機能が接続できますが、ウェブページは接続できません 。
特定のIDが指定されている 場合、例えば"ids": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
のように、そのアプリケーションのみ が接続できます。
matches が指定されている場合、これらのウェブアプリは接続できるようになります:
Copy "matches" : [
"https://*.google.com/*" ,
"*://*.chromium.org/*" ,
空として指定されている場合: "externally_connectable": {}
、アプリやウェブは接続できません。
ここで示されている 拡張機能とURLが少ないほど 、攻撃面は小さく なります。
もしウェブページが XSSまたはテイクオーバーに脆弱 であり、externally_connectable
に示されている場合、攻撃者は バックグラウンドスクリプトに直接メッセージを送信 でき、コンテンツスクリプトとそのCSPを完全にバイパスすることができます。
したがって、これは 非常に強力なバイパス です。
さらに、クライアントが不正な拡張機能をインストールした場合、脆弱な拡張機能と通信することが許可されていなくても、許可されたウェブページにXSSデータを注入 したり、WebRequest
や DeclarativeNetRequest
APIを悪用して、ターゲットドメインのリクエストを操作し、JavaScriptファイル のリクエストを変更することができます。(ターゲットページのCSPがこれらの攻撃を防ぐ可能性があることに注意してください)。このアイデアはこの書き込みから 来ています。
コミュニケーションの概要
拡張機能 <--> ウェブアプリ
コンテンツスクリプトとウェブページ間で通信するために、通常はポストメッセージが使用されます。したがって、ウェブアプリケーションでは通常、window.postMessage
関数への呼び出しが見られ、コンテンツスクリプトでは window.addEventListener
のようなリスナーが見られます。ただし、拡張機能は ポストメッセージを送信してウェブアプリケーションと通信 することもできるため、ウェブはそれを期待する必要があります。または、単にウェブに新しいスクリプトを読み込ませることもできます。
拡張機能内
通常、chrome.runtime.sendMessage
関数が拡張機能内でメッセージを送信するために使用され(通常は background
スクリプトによって処理されます)、受信して処理するためにリスナーが chrome.runtime.onMessage.addListener
を呼び出して宣言されます。
chrome.runtime.connect()
を使用して、単一のメッセージを送信する代わりに持続的な接続を持つことも可能で、次の例のように メッセージを送信 および受信 するために使用できます。
chrome.runtime.connect()
の例```javascript var port = chrome.runtime.connect();
// Listen for messages from the web page window.addEventListener("message", (event) => { // Only accept messages from the same window if (event.source !== window) { return; }
// Check if the message type is "FROM_PAGE" if (event.data.type && (event.data.type === "FROM_PAGE")) { console.log("Content script received: " + event.data.text); // Forward the message to the background script port.postMessage({ type: 'FROM_PAGE', text: event.data.text }); } }, false);
// Listen for messages from the background script port.onMessage.addListener(function(msg) { console.log("Content script received message from background script:", msg); // Handle the response message from the background script });
Copy </details>
バックグラウンドスクリプトから特定のタブにあるコンテンツスクリプトにメッセージを送信することも可能で、**`chrome.tabs.sendMessage`**を呼び出す際にメッセージを送信する**タブのID**を指定する必要があります。
### 許可された`externally_connectable`から拡張機能へ
`externally_connectable`設定で許可された**Webアプリと外部ブラウザ拡張機能**は、次のようにリクエストを送信できます:
```javascript
chrome.runtime.sendMessage(extensionId, ...
拡張機能ID を言及する必要がある場所。
ネイティブメッセージング
バックグラウンドスクリプトがシステム内のバイナリと通信することが可能であり、この通信が適切に保護されていない場合、RCEなどの重大な脆弱性にさらされる可能性があります 。この後で詳しく説明します 。
Copy chrome . runtime .sendNativeMessage (
'com.my_company.my_application' ,
{text : 'Hello' } ,
function (response) {
console .log ( 'Received ' + response);
}
);
Web ↔︎ コンテンツスクリプト通信
コンテンツスクリプト が動作する環境とホストページが存在する環境は分離 されており、隔離 が確保されています。この隔離にもかかわらず、両者はページのドキュメントオブジェクトモデル (DOM) 、つまり共有リソースと相互作用する能力を持っています。ホストページがコンテンツスクリプト と通信するため、またはコンテンツスクリプトを介して拡張機能と間接的に通信するためには、両者がアクセス可能なDOM を通信チャネルとして利用する必要があります。
ポストメッセージ
Copy // This is like "chrome.runtime.sendMessage" but to maintain the connection
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);
// Forward the message to the background script
port .postMessage ( event . data .text);
}
} , false );
Copy document .getElementById ( "theButton" ) .addEventListener ( "click" , () => {
window .postMessage (
{type : "FROM_PAGE" , text : "Hello from the webpage!" } , "*" );
} , false );
安全なPost Message通信は、受信したメッセージの信頼性を確認する必要があります。これは以下を確認することで行えます:
event.isTrusted
: これは、イベントがユーザーのアクションによってトリガーされた場合のみTrueになります。
コンテンツスクリプトは、ユーザーが何らかのアクションを実行した場合にのみメッセージを期待するかもしれません。
origin domain : メッセージを期待する場合は、許可リストのドメインのみを許可するかもしれません。
正規表現が使用される場合は、非常に注意が必要です。
Source : received_message.source !== window
を使用して、メッセージがコンテンツスクリプトがリスニングしている同じウィンドウから のものであるかを確認できます。
前述のチェックは、実施されていても脆弱である可能性があるため、次のページで潜在的なPost Messageバイパス を確認してください:
Iframe
別の通信方法としてIframe URLs を通じて行うことが考えられます。例は以下にあります:
DOM
これは「正確には」通信方法ではありませんが、ウェブとコンテンツスクリプトはウェブDOMにアクセスできます 。したがって、コンテンツスクリプト がそこから情報を読み取っている場合、ウェブDOMを信頼している と、ウェブはこのデータを変更する可能性があります (ウェブは信頼されるべきではないため、またはウェブがXSSに対して脆弱であるため)し、コンテンツスクリプトを危険にさらす 可能性があります。
ブラウザ拡張を危険にさらすためのDOMベースのXSSの例 も以下にあります:
コンテンツスクリプト ↔︎ バックグラウンドスクリプト通信
コンテンツスクリプトは、runtime.sendMessage() または tabs.sendMessage() を使用して、一度きりのJSONシリアライズ可能な メッセージを送信できます。
レスポンス を処理するには、返されたPromise を使用します。ただし、後方互換性のために、最後の引数としてコールバック を渡すこともできます。
コンテンツスクリプト からリクエストを送信するのは次のようになります:
Copy ( async () => {
const response = await chrome . runtime .sendMessage ({greeting : "hello" });
// do something with response here, not outside the function
console .log (response);
})();
拡張機能 からリクエストを送信する(通常はバックグラウンドスクリプト )。選択したタブのコンテンツスクリプトにメッセージを送信する方法の例:
Copy // 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 イベントリスナー を設定する必要があります。これは、コンテンツスクリプトまたは拡張ページから見ると同じように見えます。
Copy // 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()
関数に関連付けられたコールバックがデフォルトでトリガーされます。
ネイティブメッセージング
ブラウザ拡張機能は、標準入力を介してシステム内のバイナリと通信することも可能です 。アプリケーションは、次のようなjsonを示すjsonをインストールする必要があります:
Copy {
"name" : "com.my_company.my_application" ,
"description" : "My Application" ,
"path" : "C:\\Program Files\\My Application\\chrome_native_messaging_host.exe" ,
"type" : "stdio" ,
"allowed_origins" : [ "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/" ]
}
name
は runtime.connectNative()
または runtime.sendNativeMessage()
に渡される文字列で、ブラウザ拡張のバックグラウンドスクリプトからアプリケーションと通信するために使用されます。 path
はバイナリへのパスで、1つの有効な type
は stdio(stdin と stdout を使用)であり、 allowed_origins
はアクセスできる拡張機能を示します(ワイルドカードは使用できません)。
Chrome/Chromium は、この JSON をいくつかの Windows レジストリや macOS および Linux のいくつかのパスで検索します(詳細は docs を参照)。
ブラウザ拡張は、この通信を使用できるようにするために nativeMessaing
権限を宣言する必要があります。
これが、ネイティブアプリケーションにメッセージを送信するバックグラウンドスクリプトコードの例です:
Copy chrome . runtime .sendNativeMessage (
'com.my_company.my_application' ,
{text : 'Hello' } ,
function (response) {
console .log ( 'Received ' + response);
}
);
In このブログ投稿 では、ネイティブメッセージを悪用する脆弱なパターンが提案されています:
ブラウザ拡張機能はコンテンツスクリプトのためのワイルドカードパターンを持っています。
コンテンツスクリプトはsendMessage
を使用してバックグラウンドスクリプトにpostMessage
メッセージを渡します。
バックグラウンドスクリプトはsendNativeMessage
を使用してネイティブアプリケーションにメッセージを渡します。
ネイティブアプリケーションはメッセージを危険に扱い、コード実行につながります。
その中で、ブラウザ拡張機能を悪用して任意のページからRCEに移行する例が説明されています 。
メモリ/コード/クリップボード内の機密情報
ブラウザ拡張機能がメモリ内に機密情報を保存している場合 、これはダンプ され(特にWindowsマシンで)、この情報が検索 される可能性があります。
したがって、ブラウザ拡張機能のメモリは安全とは見なされるべきではなく 、資格情報やニーモニックフレーズなどの機密情報は保存されるべきではありません 。
もちろん、コード内に機密情報を置かないでください 、それは公開される からです。
ブラウザからメモリをダンプするには、プロセスメモリをダンプする か、ブラウザ拡張機能の設定 に行き、**Inspect pop-up
**をクリック -> **Memory
**セクション -> **Take a snapshot
を選択し、 CTRL+F
**でスナップショット内の機密情報を検索します。
さらに、ニーモニックキーやパスワードのような非常に機密性の高い情報は、クリップボードにコピーされることを許可すべきではありません (または少なくとも数秒以内にクリップボードから削除するべきです)なぜなら、その後クリップボードを監視しているプロセスがそれらを取得できるからです。
ブラウザに拡張機能を読み込む
chrome://extensions/
に移動し、 Developer Mode
を有効にします 。
**Load unpacked
**ボタンをクリックします。
Firefox では、**about:debugging#/runtime/this-firefox
に移動し、 Load Temporary Add-on
**ボタンをクリックします。
ストアからソースコードを取得する
Chrome拡張機能のソースコードは、さまざまな方法で取得できます。以下は各オプションの詳細な説明と手順です。
コマンドラインを使用してZIPとして拡張機能をダウンロード
Chrome拡張機能のソースコードは、コマンドラインを使用してZIPファイルとしてダウンロードできます。これは、curl
を使用して特定のURLからZIPファイルを取得し、その後ZIPファイルの内容をディレクトリに抽出することを含みます。手順は以下の通りです:
"extension_id"
を拡張機能の実際のIDに置き換えます。
Copy 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/
CRX Viewer拡張機能を使用する
もう一つの便利な方法は、オープンソースプロジェクトであるChrome Extension Source Viewerを使用することです。これはChrome Web Store からインストールできます。ビューワーのソースコードはそのGitHubリポジトリ で入手可能です。
ローカルにインストールされた拡張機能のソースを表示する
ローカルにインストールされたChrome拡張機能も検査できます。方法は以下の通りです:
chrome://version/
にアクセスし、「Profile Path」フィールドを見つけて、Chromeのローカルプロファイルディレクトリにアクセスします。
プロファイルディレクトリ内のExtensions/
サブフォルダに移動します。
このフォルダには、通常は読みやすい形式のソースコードを持つすべてのインストールされた拡張機能が含まれています。
拡張機能を特定するには、IDを名前にマッピングできます:
about:extensions
ページで開発者モードを有効にして、各拡張機能のIDを表示します。
各拡張機能のフォルダ内のmanifest.json
ファイルには、拡張機能を特定するのに役立つ読みやすいname
フィールドが含まれています。
ファイルアーカイバまたはアンパッカーを使用する
Chrome Web Storeに行き、拡張機能をダウンロードします。ファイルは.crx
拡張子を持っています。ファイルの拡張子を.crx
から.zip
に変更します。任意のファイルアーカイバ(WinRAR、7-Zipなど)を使用してZIPファイルの内容を抽出します。
Chromeで開発者モードを使用する
Chromeを開き、chrome://extensions/
に移動します。右上で「開発者モード」を有効にします。「未パッケージ化の拡張機能を読み込む...」をクリックします。拡張機能のディレクトリに移動します。これはソースコードをダウンロードするものではありませんが、すでにダウンロードまたは開発された拡張機能のコードを表示および変更するのに便利です。
Chrome拡張機能マニフェストデータセット
脆弱なブラウザ拡張機能を見つけるために、https://github.com/palant/chrome-extension-manifests-dataset を使用し、マニフェストファイルに潜在的な脆弱性の兆候がないか確認できます。たとえば、25000人以上のユーザーを持つ拡張機能、content_scripts
、および権限nativeMessaging
を確認するには:
Copy # Query example from https://spaceraccoon.dev/universal-code-execution-browser-extensions/
node query.js -f "metadata.user_count > 250000" "manifest.content_scripts?.length > 0 && manifest.permissions?.includes('nativeMessaging')"
セキュリティ監査チェックリスト
ブラウザ拡張機能は限られた攻撃面 を持っていますが、その中には脆弱性 や強化の可能性 が含まれている場合があります。以下は最も一般的なものです:
ブラウザ拡張機能のリスク
ツール
提供されたChromeウェブストアリンクから任意のChrome拡張機能を取得します。
潜在的なClickjacking分析 : web_accessible_resources ディレクティブが設定された拡張機能のHTMLページを検出します。これらはページの目的に応じてClickjackingに対して脆弱である可能性があります。
権限警告ビューワー :ユーザーが拡張機能をインストールしようとしたときに表示されるすべてのChrome権限プロンプト警告のリストを表示します。
危険な関数 :攻撃者によって悪用される可能性のある危険な関数の場所を示します(例:innerHTML、chrome.tabs.executeScriptなど)。
エントリポイント :拡張機能がユーザー/外部入力を受け取る場所を示します。これは拡張機能の表面積を理解し、悪意のあるデータを拡張機能に送信する潜在的なポイントを探すのに役立ちます。
危険な関数とエントリポイントスキャナーは、生成されたアラートに対して以下を持っています:
コードを含む完全なソースファイルを表示するための「ファイルを表示」ボタン。
アラートが発生したファイルの完全なChrome拡張機能URI。
バックグラウンドページスクリプト、コンテンツスクリプト、ブラウザアクションなど、ファイルの種類。
コンテンツセキュリティポリシー(CSP)分析およびバイパスチェッカー :これにより、拡張機能のCSPの弱点が指摘され、ホワイトリストに登録されたCDNなどによるCSPのバイパスの潜在的な方法が明らかになります。
既知の脆弱なライブラリ :これはRetire.js を使用して、既知の脆弱なJavaScriptライブラリの使用をチェックします。
拡張機能とフォーマットされたバージョンをダウンロード。
拡張機能の美化されたバージョンをダウンロード(自動整形されたHTMLとJavaScript)。
スキャン結果の自動キャッシュ。拡張機能のスキャンを初めて実行する際にはかなりの時間がかかります。しかし、拡張機能が更新されていない限り、2回目は結果がキャッシュされるため、ほぼ瞬時に完了します。
リンク可能なレポートURL。簡単に他の人にTarnishによって生成された拡張機能レポートへのリンクを提供できます。
プロジェクトNetoは、FirefoxやChromeなどの有名なブラウザのブラウザプラグインや拡張機能の隠れた機能を分析し、解明するために考案されたPython 3パッケージです。manifest.json
、ローカリゼーションフォルダ、JavaScriptおよびHTMLソースファイルなどの関連リソースからこれらの機能を抽出するために、パッケージ化されたファイルを解凍するプロセスを自動化します。
参考文献