我的 Electron 客户端被第三方页面入侵了

简介: 公司有个内部项目是用 Electron 来开发的,有个功能需要像浏览器一样加载第三方站点。本来一切安好,但是某天打开某个站点的链接,导致 整个客户端直接变成了该站点的页面。这一看就是该站点做了特殊的处理,经排查网页源码后,果然发现了有这么一句代码。

问题描述

公司有个内部项目是用 Electron 来开发的,有个功能需要像浏览器一样加载第三方站点。


本来一切安好,但是某天打开某个站点的链接,导致 整个客户端直接变成了该站点的页面


这一看就是该站点做了特殊的处理,经排查网页源码后,果然发现了有这么一句代码。

if (window.top !== window.self) {
      window.top.location = window.location;
    }

翻译一下就是:如果当前窗口不是顶级窗口的话,将当前窗口设置为顶级窗口。


奇怪的是两者不是 跨域 了吗,为什么 iframe 还可以影响顶级窗口。


先说一下我当时的一些解决办法:

  1. 用 webview 替换 iframe
  2. 给 iframe 添加 sandbox 属性


后续内容就是一点复盘工作。

场景复现(Web端)

一开始怀疑是客户端的问题,所以我用在纯 Web 上进行了一次对比验证。


这里我们新建两个文件:1.html 和 2.html,我们称之为 页面A页面B


然后起了两个本地服务器来模拟同源与跨域的情况。

符合同源策略

<body>
  <h1>这是页面A</h1>
  <!-- 这是同源的情况 -->
  <iframe id="iframe" src="http://127.0.0.1:5500/2.html" />
  
  <script>
    iframe.onload = () => {
      console.log('iframe loaded..')
      console.log('子窗口路径', iframe.contentWindow.location.href)
    }
  </script>
</body>
<body>
  <h2>这是页面B</h2>
  <script>
    console.log('page2...')
    console.log(window === window.top)
    console.log('顶部窗口路径', window.top.location.href)
  </script>
</body>

我们打开控制台可以看到 页面A 和 页面B 是可以 互相访问 到对方窗口的路径。

1722839637000.jpg

如果这个时候在 页面B 加上文章开头提到的 代码片段,那么显然页面将会发生变化。

1722839645619.jpg

跨域的情况

这时候我们修改 页面A 加载 页面B 的地址,使其不符合同源策略。

1722839663758.jpg

理所应当的是,两个页面不能够相互访问了,这才是正常的,否则内嵌第三方页面可以互相修改,那就太不安全了。

场景复现(客户端)

既然 Web 端是符合预期的,那是不是 Electron 自己的问题呢?


我们通过 electron-vite 快速搭建了一个 React模板的electron应用,版本为:electron@22.3.27,并且在 App 中也嵌入了刚才的 页面B。

function App(): JSX.Element {
  return (
    <>
      <h1>这是Electron页面</h1>
      <iframe id="iframe" src="http://localhost:3000/2.html"/>
    </>
  )
}
export default App

1722839688711.jpg

对不起,干干净净的 Electron 根本不背这个锅,在它身上的表现如同 Web端 一样,也受同源策略的限制。


那么肯定是我的项目里有什么特殊的配置,通过对比主进程的代码,答案终于揭晓。

new BrowserWindow({
    ...,
    webPreferences: {
        ...,
        webSecurity: false // 就是因为它
    }
})

Electron 官方文档 里是这么描述 webSecurity 这个配置的。


webSecurity boolean (可选) - 当设置为 false, 它将禁用同源策略 (通常用来测试网站), 如果此选项不是由开发者设置的,还会把 allowRunningInsecureContent设置为 true. 默认值为 true。


也就是说,Electron本身是有一层屏障的,但当该属性设置为 false 的时候,我们的客户端将会绕过同源策略的限制,这层屏障也就消失了,因此 iframe 的行为表现得像是嵌套了同源的站点一样。

解决方案

把这个配置去掉,确实是可以解决这个问题,但考虑到可能对其他功能造成的影响,只能采取其他方案。


如文章开头提到的,用 webview 替换 iframe。


webview 是 Electron的一个自定义元素(标签),可用于在应用程序中嵌入第三方网页,它默认开启安全策略,直接实现了主应用与嵌入页面的隔离。


因为目前这个需求是仅作展示,不需要与嵌套页面进行交互以及复杂的通信,因此在一开始的开发过程中,并没有使用它,而是直接采用了 iframe。


而 iframe 也能够实现类似的效果,只需要添加一个 sandbox 属性可以解决。


MDN 中提到,sandbox 控制应用于嵌入在 <iframe> 中的内容的限制。该属性的值可以为空以应用所有限制,也可以为空格分隔的标记以解除特定的限制。


如此一来,就算是同源的,两者也不会互相干扰。

总结

这不是一个复杂的问题,发现后及时修复了,并没有造成很大的影响(还好是自己人用的平台)。


写这篇文章的主要目的是为了记录这次事件,让我意识到在平时开发过程中,把注意力过多的放在了 业务、样式、性能等这些看得见的问题上,可能很少关注甚至忽略了 安全 这一要素,以为前端框架能够防御像 XSS 这样的攻击就能安枕无忧。


谨记,永远不要相信第三方,距离产生美。


如有纰漏,欢迎在评论区指出。

相关文章
|
2月前
|
JavaScript 网络安全 iOS开发
如何用 Electron 打包chatgpt-plus.top并生成mac客户端
如何用 Electron 打包chatgpt-plus.top并生成mac客户端
31 0
|
移动开发 JavaScript 前端开发
【浏览器&exe桌面应用】用nw.js &Electron -HTML和JavaScript制作exe桌面程序-打造浏览器,查询机客户端,大屏展示客户端
【浏览器&exe桌面应用】用nw.js &Electron -HTML和JavaScript制作exe桌面程序-打造浏览器,查询机客户端,大屏展示客户端
166 0
|
存储 网络协议 JavaScript
IM跨平台技术学习(四):蘑菇街基于Electron开发IM客户端的技术实践
本篇将回到IM即时通讯技术本身,根据蘑菇街的实际技术实践,总结和分享基于Electron开发跨平台IM客户端的过程中,需要考虑的典型技术问题以及我们的解决方案。希望能给你带来帮助。
374 0
IM跨平台技术学习(四):蘑菇街基于Electron开发IM客户端的技术实践
|
资源调度 前端开发 JavaScript
Electron搭配React的history路由模式打包exe客户端
Electron安装 安装问题 npm或者yarn安装electron就算是配置了淘宝源还是会出现超时。所以我的解决方案是安装cnpm,使用cnpm去安装。 全局安装cnpm npm i cnpm -G 复制代码 新建项目 cnpm init // 一路Enter然后到最后一步输入yes
636 0
|
1月前
|
JavaScript 开发工具
Electron 开发过程中主进程的无法看到 console.log 输出怎么办
Electron 开发过程中主进程的无法看到 console.log 输出怎么办
|
2月前
|
前端开发
PC端01,桌面端,electron的开发,electron的开发的系列课程,软件开发必备流程,electron的讲解,electron的开发,vitepress博主的gitee链接,PC端效率软件
PC端01,桌面端,electron的开发,electron的开发的系列课程,软件开发必备流程,electron的讲解,electron的开发,vitepress博主的gitee链接,PC端效率软件
PC端01,桌面端,electron的开发,electron的开发的系列课程,软件开发必备流程,electron的讲解,electron的开发,vitepress博主的gitee链接,PC端效率软件
|
4月前
|
移动开发 开发框架 JavaScript
Vue3 Vite electron 开发桌面程序
Vue3 Vite electron 开发桌面程序
295 0
|
10月前
|
前端开发 算法 JavaScript
从零开始开发图床工具:使用 Gitee 和 Electron 实现上传、管理和分享(下)
从零开始开发图床工具:使用 Gitee 和 Electron 实现上传、管理和分享(下)
148 0
|
10月前
|
存储 Web App开发 JavaScript
从零开始开发图床工具:使用 Gitee 和 Electron 实现上传、管理和分享(上)
从零开始开发图床工具:使用 Gitee 和 Electron 实现上传、管理和分享(上)
198 0
|
Web App开发 资源调度 前端开发
基于NeteaseCloudMusicApi和electron-vue开发网易云音乐--electron-vue初始化
基于NeteaseCloudMusicApi和electron-vue开发网易云音乐--electron-vue初始化
114 0