# Electron Desktop Apps
{% hint style="success" %}
Learn & practice AWS Hacking:[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)\
Learn & practice GCP Hacking: [**HackTricks Training GCP Red Team Expert (GRTE)**](https://training.hacktricks.xyz/courses/grte)
Support HackTricks
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
{% endhint %}
## Introduction
Electron combines a local backend (with **NodeJS**) and a frontend (**Chromium**), although tt lacks some the security mechanisms of modern browsers.
Usually you might find the electron app code inside an `.asar` application, in order to obtain the code you need to extract it:
```bash
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
```
In the source code of an Electron app, inside `packet.json`, you can find specified the `main.js` file where security configs ad set.
```json
{
"name": "standard-notes",
"main": "./app/index.js",
```
Electron has 2 process types:
* Main Process (has complete access to NodeJS)
* Renderer Process (should have NodeJS restricted access for security reasons)
![](<../../../.gitbook/assets/image (182).png>)
A **renderer process** will be a browser window loading a file:
```javascript
const {BrowserWindow} = require('electron');
let win = new BrowserWindow();
//Open Renderer Process
win.loadURL(`file://path/to/index.html`);
```
Settings of the **renderer process** can be **configured** in the **main process** inside the main.js file. Some of the configurations will **prevent the Electron application to get RCE** or other vulnerabilities if the **settings are correctly configured**.
The electron application **could access the device** via Node apis although it can be configure to prevent it:
* **`nodeIntegration`** - is `off` by default. If on, allows to access node features from the renderer process.
* **`contextIsolation`** - is `on` by default. If off, main and renderer processes aren't isolated.
* **`preload`** - empty by default.
* [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - is off by default. It will restrict the actions NodeJS can perform.
* Node Integration in Workers
* **`nodeIntegrationInSubframes`**- is `off` by default.
* If **`nodeIntegration`** is **enabled**, this would allow the use of **Node.js APIs** in web pages that are **loaded in iframes** within an Electron application.
* If **`nodeIntegration`** is **disabled**, then preloads will load in the iframe
Example of configuration:
```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
}
};
```
Some **RCE payloads** from [here](https://7as.es/electron/nodeIntegration\_rce.txt):
```html
Example Payloads (Windows):
Example Payloads (Linux & MacOS):
```
### Capture traffic
Modify the start-main configuration and add the use of a proxy such as:
```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
```
## Electron Local Code Injection
If you can execute locally an Electron App it's possible that you could make it execute arbitrary javascript code. Check how in:
{% content-ref url="../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md" %}
[macos-electron-applications-injection.md](../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md)
{% endcontent-ref %}
## RCE: XSS + nodeIntegration
If the **nodeIntegration** is set to **on**, a web page's JavaScript can use Node.js features easily just by calling the `require()`. For example, the way to execute the calc application on Windows is:
```html
```
## RCE: preload
The script indicated in this setting is l**oaded before other scripts in the renderer**, so it has **unlimited access to Node APIs**:
```javascript
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
```
Therefore, the script can export node-features to pages:
{% code title="preload.js" %}
```javascript
typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};
```
{% endcode %}
{% code title="index.html" %}
```html
```
{% endcode %}
{% hint style="info" %}
**If `contextIsolation` is on, this won't work**
{% endhint %}
## RCE: XSS + contextIsolation
The _**contextIsolation**_ introduces the **separated contexts between the web page scripts and the JavaScript Electron's internal code** so that the JavaScript execution of each code does not affect each. This is a necessary feature to eliminate the possibility of RCE.
If the contexts aren't isolated an attacker can:
1. Execute **arbitrary JavaScript in renderer** (XSS or navigation to external sites)
2. **Overwrite the built-in method** which is used in preload or Electron internal code to own function
3. **Trigger** the use of **overwritten function**
4. RCE?
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
{% content-ref url="electron-contextisolation-rce-via-preload-code.md" %}
[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](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](electron-contextisolation-rce-via-ipc.md)
{% endcontent-ref %}
### Bypass click event
If there are restrictions applied when you click a link you might be able to bypass them **doing a middle click** instead of a regular left click
```javascript
window.addEventListener('click', (e) => {
```
## RCE via shell.openExternal
For more info about this examples check [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) and [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
hen deploying an Electron desktop application, ensuring the correct settings for `nodeIntegration` and `contextIsolation` is crucial. It's established that **client-side remote code execution (RCE)** targeting preload scripts or Electron's native code from the main process is effectively prevented with these settings in place.
Upon a user interacting with links or opening new windows, specific event listeners are triggered, which are crucial for the application's security and functionality:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
These listeners are **overridden by the desktop application** to implement its own **business logic**. The application evaluates whether a navigated link should be opened internally or in an external web browser. This decision is typically made through a function, `openInternally`. If this function returns `false`, it indicates that the link should be opened externally, utilizing the `shell.openExternal` function.
**Here is a simplified pseudocode:**
![https://miro.medium.com/max/1400/1\*iqX26DMEr9RF7nMC1ANMAA.png](<../../../.gitbook/assets/image (261).png>)
![https://miro.medium.com/max/1400/1\*ZfgVwT3X1V\_UfjcKaAccag.png](<../../../.gitbook/assets/image (963).png>)
Electron JS security best practices advise against accepting untrusted content with the `openExternal` function, as it could lead to RCE through various protocols. Operating systems support different protocols that might trigger RCE. For detailed examples and further explanation on this topic, one can refer to [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), which includes Windows protocol examples capable of exploiting this vulnerability.
**Examples of Windows protocol exploits include:**
```html
```
## Reading Internal Files: XSS + contextIsolation
**Disabling `contextIsolation` enables the use of `` tags**, similar to `