前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Fuse | Electron 安全

Fuse | Electron 安全

作者头像
意大利的猫
发布2024-05-17 19:58:48
870
发布2024-05-17 19:58:48
举报
文章被收录于专栏:漫流砂漫流砂

0x01 简介

大家好,今天和大家讨论的是 fuse , fuse 直译过来是保险丝,官方文档中翻译为包特性切换

Electron 开发的应用有很多特性,能够为一些场景提供帮助,但并不是所有的场景都会用到这些特性,因此对于普通开发者来说,你默认给我开发的程序带了一堆特性,我可能还用不到,甚至可能还不太安全,我是不是应该有禁用的选项,例如,99%的应用都没有使用ELECTRON_RUN_AS_NODE,开发者希望能够提供无法使用该功能的二进制文件。

这就是 Fuse

公众号开启了留言功能,欢迎大家留言讨论~

这篇文章也提供了 PDF 版本及 Github ,见文末

0x02 当前可用的 fuse

fuse 还在随着版本不断增加,这篇文章只讨论目前(2024-05-10)的情况

fuse

作用

默认状态

runAsNode

runAsNode 是否考虑ELECTRON_RUN_AS_NODE环境变量。请注意,如果禁用此fuse,则主进程中的process.fork将无法按预期运行,因为它依赖于此环境变量来运行

Enabled

cookieEncryption

cookieEncryption 磁盘上的cookie存储是否使用操作系统级别的加密密钥进行加密。默认情况下,Chromium用于存储cookie的sqlite数据库以明文形式存储值。如果您希望确保您的应用程序cookie以与Chrome相同的方式加密,则应启用此 fuse

Disabled

nodeOptions

nodeOptions 是否考虑NODE_OPTIONS和NODE_EXTRA_CA_CERTS 环境变量。此环境变量可用于将各种自定义选项传递到Node.js运行时,并且通常不被生产中的应用程序使用。大多数应用程序可以安全地禁用此 fuse

Enabled

nodeCliInspect

nodeCliInspect 是否遵守--inspect、--inspect-brk 等标志。禁用时,它还确保 SIGUSR 1信号不会初始化主进程检查器。大多数应用程序可以安全地禁用此fuse。

Enabled

embeddedAsarIntegrityValidation

embeddedAsarIntegrityValidation 是 macOS上的一项实验性功能,该功能在加载 app.asar文件时验证其内容。此功能旨在将性能影响降至最低,但可能会略微降低从 app.asar 存档中读取文件的速度

Disabled

onlyLoadAppFromAsar

onlyLoadAppFromAsar 改变了Electron用来定位应用程序代码的搜索系统。默认情况下,Electron将按照以下顺序搜索 app.asar -> app -> default_app.asar。当这个fuse 被启用时,搜索顺序变成了一个单一条目的 app.asar,从而确保当与embeddedAsarIntegrityValidation fuse结合使用时,不可能加载未经验证的代码。

Disabled

loadBrowserProcessSpecificV8Snapshot

loadBrowserProcessSpecificV8Snapshot 更改浏览器进程使用的V8快照文件。默认情况下,Electron的进程都将使用相同的V8快照文件。启用此fuse后,浏览器进程将使用名为browser_v8_context_snapshot.bin 的文件作为其V8快照。其他进程将使用它们通常使用的V8快照文件

Disabled

grantFileProtocolExtraPrivileges

grantFileProtocolExtraPrivileges 从 file:// 协议加载的页面是否被赋予超出它们在传统Web浏览器中所获得的权限的权限。在Electron的原始版本中,这种行为是Electron应用程序的核心,但不再需要,因为应用程序现在应该从自定义协议中提供本地文件。如果您不从 file://中提供页面,则应禁用此fuse

Enabled

但是经过我的实际测试,发现 Electron Forge ,也就是官方推荐的打包工具默认的 Fuse 配置如下

forge.config.js

代码语言:javascript
复制
const { FusesPlugin } = require('@electron-forge/plugin-fuses');
const { FuseV1Options, FuseVersion } = require('@electron/fuses');

module.exports = {
  packagerConfig: {
    asar: true,
  },
  rebuildConfig: {},
  makers: [
    {
      name: '@electron-forge/maker-squirrel',
      config: {},
    },
    {
      name: '@electron-forge/maker-zip',
      platforms: ['darwin'],
    },
    {
      name: '@electron-forge/maker-deb',
      config: {},
    },
    {
      name: '@electron-forge/maker-rpm',
      config: {},
    },
  ],
  plugins: [
    {
      name: '@electron-forge/plugin-auto-unpack-natives',
      config: {},
    },
    // Fuses are used to enable/disable various Electron functionality
    // at package time, before code signing the application
    new FusesPlugin({
      version: FuseVersion.V1,
      [FuseV1Options.RunAsNode]: false,
      [FuseV1Options.EnableCookieEncryption]: true,
      [FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
      [FuseV1Options.EnableNodeCliInspectArguments]: false,
      [FuseV1Options.EnableEmbeddedAsarIntegrityValidation]: true,
      [FuseV1Options.OnlyLoadAppFromAsar]: true,
    }),
  ],
};

可以看到,除了 loadBrowserProcessSpecificV8SnapshotgrantFileProtocolExtraPrivileges 其他的与官网标记的默认值完全相反,我们看一下实际打包出来的程序

和上面的配置一致

所以你说官方设置默认值不太符合默认即安全吧,它打包工具里给你自动重新设置了值,你说他默认即安全吧,还没有把安全的值设置为默认,奇奇怪怪

0x03 如何查看程序的 fuse

检查一个应用程序的 fuse 设置

https://www.electronjs.org/zh/docs/latest/tutorial/fuses#how-do-i-flip-the-fuses

需要安装 @electron/fuses 依赖包

代码语言:javascript
复制
npm i @electron/fuses

检查应用程序的 fuse

代码语言:javascript
复制
npx @electron/fuses read --app /Applications/Foo.app

0x04 特性可能带来的危害

现在的情况是官方比较幽默,fuse 的默认值设置的像是安全在为功能让步,但打包工具又反转过来,当然我们作为安全研究人员更希望向默认即安全的建设方向去走

我们接下来就看一下这些特性可能带来的危害

1. runAsNode

runAsNode 特性的含义是程序当作普通的 Node.js 进程启动,如果是普通的 Node.js ,那么可以给该程序传递很多启动参数,官方的文档说是否考虑 ELECTRON_RUN_AS_NODE 环境变量

ELECTRON_RUN_AS_NODE 参考如下文档 https://www.electronjs.org/zh/docs/latest/api/environment-variables#electron_run_as_node

文档中说默认情况下,除了以下标志,标准的 cli 选项传递给程序都会生效

  • --openssl-config
  • --use-bundled-ca
  • --use-openssl-ca
  • --force-fips
  • --enable-fips

这些标志无效是因为 Electron 在构建 Node.js 的 crypto 模块时使用 BoringSSL 而不是 OpenSSL

cli 选项可以参考 https://nodejs.org/api/cli.html

现在我编译一个 runAsNodeEnabled 的程序

尝试通过设置环境变量 ELECTRON_RUN_AS_NODE=1 并传递 -i 参数

成功实现本地命令执行

Windows 和 MacOS 也成功执行系统命令

2. nodeCliInspect

这个 fuse 就是之前的 远程调试的利用 文章了,这个fuse 决定是否可以进行远程调试

如果设置允许远程调试,情况如下

如果设置不允许远程调试,则情况如下

远程调试无法启动

runAsNode 被设置为 Enable ,但是远程调试被设置为 Disabled 时会怎么样呢?

在 Windows 平台上并不会开启远程调试,但在 Deepin Linux 上则不同

Deepin Linux 上,当 runAsNodenodeCliInspect 其中一个被设置为 Enabled ,就可以进行远程调试

在 MacOS 上表现如何呢

runAsNodeEnable ,远程调试设置为 Disabled

runAsNode 和远程调试都设置为 Disabled

无法执行远程调试

runAsNodeDisabled ,远程调试设置为 Enabled

可以远程调试

所以 nodeCliInspect 这个 fuse 的效果设置在 MacOS 和 Deepin Linux 上表现一致,即当 runAsNodenodeCliInspect 其中一个被设置为 Enabled ,就可以进行远程调试

在 Windows 11 上则只有当 nodeCliInspect 被设置为 Enabled 时才可以进行远程调试,与 runAsNode 无关

不过 Electron 还在发展,在未来可能还会有变化

3. nodeOptions

这个 fuse 是决定程序是否要使用两个环境变量 NODE_OPTIONSNODE_EXTRA_CA_CERTS

https://nodejs.org/api/cli.html#node_optionsoptions https://github.com/nodejs/node/blob/main/doc/api/cli.md#node_extra_ca_certsfile

这个 fuse 只在 runAsNode 被设置为 Enabled 时有效,其实就是给 Node.js 传递的那些参数被写进了这个环境变量里

关闭 runAsNode

就无法运行 Node.js 代码并执行系统命令了

4. grantFileProtocolExtraPrivileges

这个 fuse 是关于 file:// 协议的,在 Electronfile:// 协议比 web 浏览器中的 file:// 协议具备更强大的功能,包括但不限于

  • file:// 协议加载的页面可以通过 fetch 加载其他file:// 协议的资源
  • file:// 协议加载的页面能够使用 service workers
  • file:// 协议加载的页面能够访问子 frames
  • file:// 无视沙盒限制

官方推荐,加载本地文件尽可能使用自定义协议,而不是开启这个 fuse ,对于旧版本 Electron ,这是核心功能,所以默认开启;在 Electron Forge 中也没有对其进行额外设置,这是合理的,毕竟不是所有开发者都会去自定义协议

我们尝试直接使用 fiddle 进行测试第一项

确实可以获取到数据,而且之前就测试过,file 协议之间没有同源策略限制

现在我们将程序用 Electron Forge 进行打包

不仅使用 fetch 请求 file:// 协议资源不可用了,通过 file:// 创建主窗口都不行了,可能需要对路径进行配置,但明确的是使用 fetch 请求 file:// 协议资源这种特权没有了

5. CVE-2024-23743

这个 CVE 就是上面提到的 runAsNodenodeCliInspect 开启的效果,有一些安全研究员直接给提交 CVE 了,我看了一下,好像还提交了不少,为此官方在博客中专门谈了一下这个问题

官方的态度首先是认为描述不准确,提交者认为这是一个远程代码执行,并且认定是严重 critical,其实是强调和 Chrome 的漏洞模型保持一致,不考虑本地物理攻击

其实这些 fuse 的问题是因为在一场安全大会上,有位安全研究员提出来的,并且还制作了一个检测工具,具体官方声明以及检测工具查看下方链接

https://www.electronjs.org/zh/blog/statement-run-as-node-cves https://github.com/r3ggi/electroniz3r

0x05 修改程序的 fuse

程序的 fuse 是可以手动修改的,由于 fuse 是在签名前打包时候设置的,所以在签名后修改 fuse 应该会导致签名失效

有两种方式,一种是使用官方的工具 @electron/fuses ,另一种方式是直接修改二进制文件,官方提供了一些格式信息,但显然,官方的工具是更简单的

可以看到,当前程序的 RunAsNodeDisabled 的,也就是无法当作 Node.js 执行

现在我们尝试翻转 RunAsNode

现在 RunAsNode 变成 Enabled 了,尝试执行 Node.js

接下来我们测试一下,将 vscode 的 fuse 翻转后,它的签名是否依旧有效

"C:\Users\join\AppData\Local\Programs\Microsoft VS Code\Code.exe"

读取 VSCode 的 fuse

代码语言:javascript
复制
npx @electron/fuses read --app "C:\Users\join\AppData\Local\Programs\Microsoft VS Code\Code.exe"

备份好原文件后,尝试将 RunAsNode 设置为 Disabled

成功翻转 RunAsNode 的设置,我们看一下签名情况

果然,签名失效

是否可以正常执行呢?

功能依旧正常,我们尝试再翻转一次,看看能不能让签名再次生效

签名又恢复了正常,这有点意思

0x06 总结

Electron 开发的程序默认会带有一些特性,然而这些特性并不总是能用到,甚至很多特性大部分开发者都用不到,所以官方给了一个总开关,可以在打包等过程中,显式的关闭或启用这些特性

目前来看,这些特性能够引起的主要是本地命令执行、文件读取,主要涉及的特性如下

  • runAsNode
  • nodeCliInspect
  • nodeOptions
  • grantFileProtocolExtraPrivileges

应用程序的 fuse 是可以翻转的,官方也提供了工具,由于特性的启用与关闭是在打包过程中完成的,所以翻转已经签名的程序的fuse 会导致签名失效,但将已经翻转的fuse 再翻转一次,保持和原本的程序一致,签名就会重新生效

0x07 PDF 版 & Github

PDF

https://pan.baidu.com/s/1-wCXxWhJdH8ff3RfoRaYPw?pwd=t5hi

Github

https://github.com/Just-Hack-For-Fun/Electron-Security

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-05-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 NOP Team 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 简介
  • 0x02 当前可用的 fuse
  • 0x03 如何查看程序的 fuse
  • 0x04 特性可能带来的危害
    • 1. runAsNode
      • 2. nodeCliInspect
        • 3. nodeOptions
          • 4. grantFileProtocolExtraPrivileges
            • 5. CVE-2024-23743
            • 0x05 修改程序的 fuse
            • 0x06 总结
            • 0x07 PDF 版 & Github
            相关产品与服务
            远程调试
            远程调试(Remote Debugging,RD)在云端为用户提供上千台真实手机/定制机/模拟器设备,快速实现随时随地测试。运用云测技术对测试方式、操作体验进行了优化,具备多样性的测试能力,包括随时截图和记录调试日志,稳定的支持自动化测试, 设备灵活调度,用例高效执行, 快速定位产品功能和兼容性问题。云手机帮助应用、移动游戏快速发现和解决问题,节省百万硬件费用,加速敏捷研发流程。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档