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

nodeIntegrationInWorker | Electron 安全

作者头像
意大利的猫
发布2024-05-08 11:05:20
880
发布2024-05-08 11:05:20
举报
文章被收录于专栏:漫流砂漫流砂

0x01 简介

我是在这篇文章测试过程中发现 Electron 20.0sandbox:true 的,当时以为是官方弄错了,所以尝试跟官方沟通,等了一周多,但是官方一直没有给反馈,所以导致这篇文章比 sandbox 那篇文章发得晚了一些,

大家好,今天和大家讨论 nodeIntegrationInWorker , 这个选项看起来和 nodeIntegration 很像,不过后面跟了 InWorker ,说明是在 Worker 中开启 Node.js ,默认值为 false

问题来了,什么是 Worker 呢?我看我像是 Worker ,但是这里说的是 Web Worker

Web Worker 是一项 HTML5 提出的技术,它允许在Web应用程序中创建后台线程,以实现JavaScript的多线程处理能力。具体来说,Web Worker 是一个独立于主线程(即浏览器的UI线程)运行的JavaScript线程,用于执行耗时的、计算密集型或其他可能阻塞用户界面的任务,确保这些任务不会影响到页面的响应性和用户体验。 Web Worker 常用于以下场景:

  • 大数据处理:如批量数据过滤、排序、计算等复杂算法。
  • 图像处理:如像素操作、压缩、解码等图形处理任务。
  • 科学计算:如数学模型的迭代计算、物理模拟等高性能计算需求。
  • 离线存储处理:如 IndexedDB 数据的批量读写、同步操作。
  • 长时间运行的任务:如长轮询、定时任务、长时间运行的计数器等,避免影响页面响应性。
  • 网络通信:处理 XMLHttpRequest 或 Fetch API 请求,尤其是处理大量并发请求或流式数据。

通过使用 Web Worker,开发者能够有效地解决JavaScript单线程环境下可能出现的性能瓶颈问题,确保即使在执行繁重任务时,Web应用仍能保持流畅的用户界面和良好的响应速度。

JavaScript 多线程一直是一个非常别扭的事情,用过的人都迷糊,有了 Worker 以后应该会缓解一些

https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers https://www.electronjs.org/zh/docs/latest/api/structures/browser-window-options https://www.electronjs.org/zh/docs/latest/tutorial/multithreading

0x02 Web Worker

1. Web Worker 简介

一个 worker 是使用一个构造函数创建的一个对象(例如 Worker())运行一个命名的 JavaScript 文件

这个文件包含将在 worker 线程中运行的代码; worker 运行在另一个全局上下文中,不同于当前的window。因此,在 Worker 内通过 window 获取全局作用域(而不是self)将返回错误

Worker 分为两类

  • 专用 Worker 一对一关联,即一个 Worker 服务于一个主线程,由创建它的脚本独享
  • 共享 Worker 一对多关联,一个共享 Worker 可以被多个页面(主线程)访问和通信,适用于跨页面共享资源或协同工作

Electron 的官方描述来看,nodeIntegrationInWorker 目前只支持专用 Worker ,而且必须将 sandbox 设置为 false 才有效

关键的是,从目前 Electron 官方描述来看,Node.js 似乎还没有做好关于 Worker 的准备

https://www.electronjs.org/zh/docs/latest/tutorial/multithreading

更多关于 Web Worker 的介绍可以参考下面的文章

https://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API/Using_web_workers#%E4%B8%93%E7%94%A8_worker https://www.ruanyifeng.com/blog/2018/07/web-worker.html

2. 创建 Web Worker

如何创建一个专用 Worker 呢?

代码语言:javascript
复制
const myWorker = new Worker("worker.js");

这样就生成了一个 Web WorkerWeb Worker 会运行 worker.js 中的代码,其中 worker.js 也可以是一个URL ,但必须是同源的

3. 主线程与 Worker 通信

这有点像 Electron 中的主进程和渲染进程通信了。主线程和 Worker 线程的通信是通过 postMessageonmessage 进行通信的

worker.js

代码语言:javascript
复制
// worker.js
self.addEventListener('message', function(e) {
  const data = e.data;
  // 处理收到的数据并进行计算或处理
  const result = performComputation(data);

  // 将结果发送回主线程
  self.postMessage(result);
}, false);

function performComputation(inputData) {
  // 在这里编写具体的计算逻辑
  // ...
  return computedResult;
}

上面的代码是一个简单的计算demo ,主进程发送数据后,它便进行一些运算,并通过 postMessage 返回给主线程

主线程这边

代码语言:javascript
复制
// 创建 Worker,传入 Worker 脚本文件的路径
const myWorker = new Worker('worker.js');

// 主线程向 Worker 发送消息
myWorker.postMessage(someInputData);

// 监听 Worker 返回的结果
myWorker.addEventListener('message', function(e) {
  const result = e.data;
  console.log('Received result from Worker:', result);
  // 根据结果进行后续操作
}, false);

4. 错误处理

为确保程序健壮性,应在主线程中监听 Workererror 事件以处理 Worker 执行过程中的错误

代码语言:javascript
复制
myWorker.addEventListener('error', function(errorEvent) {
  console.error('Error occurred in Worker:', errorEvent.message);
}, false);

5. 关闭 Worker

当不再需要 Worker 时,调用 worker.terminate() 方法来停止 Worker 并释放其资源。

代码语言:javascript
复制
myWorker.terminate();

0x03 测试 nodeIntegrationInWorker

main.js

代码语言:javascript
复制
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow () {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 1600,
    height: 1200,
    webPreferences: {
      nodeIntegrationInWorker: true,
      sandbox: false,
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')
  // mainWindow.loadURL('https://iqinban.com/')

  // Open the DevTools.
  mainWindow.webContents.openDevTools()
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

index.html

代码语言:javascript
复制
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.

    <!-- You can also require other files to run in this process -->
    <script src="./renderer.js"></script>
  </body>
</html>

renderer.js

代码语言:javascript
复制
// 创建 Worker,传入 Worker 脚本文件的路径
const myWorker = new Worker('worker.js');

// 主线程向 Worker 发送消息
myWorker.postMessage("message from main -> worker");

// 监听 Worker 返回的结果
myWorker.addEventListener('message', function(e) {
  const result = e.data;
  console.log('Received result from Worker:', result);
  // 根据结果进行后续操作
}, false);

worker.js

代码语言:javascript
复制
// worker.js
self.addEventListener('message', function(e) {
  const data = e.data;
  // 处理收到的数据并进行计算或处理
  console.log(data)
  const result = "OK!!!"

  // 将结果发送回主线程
  self.postMessage(result);
}, false);

1. 功能测试

可以看到, Worker 功能是没有问题的,现在测试一下 Node.js 的能力

添加如下 Payload

代码语言:javascript
复制
require('child_process').exec('open /System/Applications/Calculator.app')

成功打开计算器,Worker 确实获得了 Node.js 的能力,此时 nodeIntegration 处于默认的 false,这两个选项之间没有关系

如果开启 sandbox

Worker 不再具备 Node.js 能力

2. 特别注意

有趣的是,我们知道,sandbox 选项默认在 Electron 20.0 中开始默认为 true,但是经过我的测试,只有当 sandbox 被显式地设置为 true 时,才会阻止 Worker 获得 Node.js 的能力,当然前提是 nodeIntegrationInWorker 被设置为 true

令人震惊的是,我顺带测试了一下 nodeIntegration

对于 nodeIntegration 来说也是一样的

3. sandbox显式地设置为 true

既然有了上面的发现,那么我们接下来的测试将 sandbox 显式地设置为 true ,看看在各个版本会不会有什么不一样

可以看到,测试了 Electron 5.0、6.0、12.0、19.0、20.0、21.0、30.0 表现是一致的,如果显式地设置了 sandbox: true ,则即使设置nodeIntegrationInWorkertrueWorker也不具备 Node.js 的能力

0x04 总结

nodeIntegrationInWorker 配置项的作用是赋予 Web Worker Node.js 的能力,这个能力只有在 sandbox 没有显式地设置为 true 时起作用

一定要注意,虽然官方曾说在 Electron 20.0 版本开始,默认对渲染进程沙盒化,但是实际测试发现,如果没有显式的设置 sandbox:true ,即使是 Electron 20.0 版本以后,也不会对 nodeIntegrationnodeIntegrationInWorkerpreloadNode.js 执行造成阻碍

0x05 PDF版 & Github

PDF

https://pan.baidu.com/s/1xdKd-mTmRaQGCFSX5_7BIw?pwd=ix74

Github

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

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 0x01 简介
  • 0x02 Web Worker
    • 1. Web Worker 简介
      • 2. 创建 Web Worker
        • 3. 主线程与 Worker 通信
          • 4. 错误处理
            • 5. 关闭 Worker
            • 0x03 测试 nodeIntegrationInWorker
              • 1. 功能测试
                • 2. 特别注意
                  • 3. sandbox显式地设置为 true
                  • 0x04 总结
                  • 0x05 PDF版 & Github
                  相关产品与服务
                  腾讯云服务器利旧
                  云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
                  http://www.vxiaotou.com