nodeIntegrationInWorker | Electron 安全

0x01 简介

我是在这篇文章测试过程中发现 Electron 20.0 ≠ sandbox: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

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

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


  • 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

  • 往期文章


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 的准备

nodeIntegrationInWorker | Electron 安全

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 呢?

const myWorker = new Worker("worker.js");

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

3. 主线程与 Worker 通信

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

worker.js

// 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 返回给主线程

主线程这边

// 创建 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 执行过程中的错误

myWorker.addEventListener('error'function(errorEvent{
  console.error('Error occurred in Worker:', errorEvent.message);
}, false);

5. 关闭 Worker

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

myWorker.terminate();

0x03 测试 nodeIntegrationInWorker

main.js

// 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({
    width1600,
    height1200,
    webPreferences: {
      nodeIntegrationInWorkertrue,
      sandboxfalse,
      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

<!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

// 创建 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

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

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

1. 功能测试

nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全

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

添加如下 Payload

require('child_process').exec('open /System/Applications/Calculator.app')
nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全

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

如果开启 sandbox

nodeIntegrationInWorker | Electron 安全

Worker 不再具备 Node.js 能力

2. 特别注意

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

nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全

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

nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全

对于 nodeIntegration 来说也是一样的

3. sandbox显式地设置为 true

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

nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全
nodeIntegrationInWorker | Electron 安全

可以看到,测试了 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

往期文章

nodeIntegrationInWorker | Electron 安全

有态度,不苟同



原文始发于微信公众号(NOP Team):nodeIntegrationInWorker | Electron 安全

版权声明:admin 发表于 2024年5月5日 下午5:59。
转载请注明:nodeIntegrationInWorker | Electron 安全 | CTF导航

相关文章