跳转与导航 | Electron 安全

0x01 简介

导航我们都知道,高德地图对吧,我们搜索一个地点,它告诉我们如何到达。对于网站来说,导航是帮助用户到达用户想去的地方(网址)

跳转与导航 | Electron 安全

Electron 中也是一样,凡是离开当前地址的操作都可以算作是跳转和导航,最常见的是点击了某个链接,之后我们进入到链接中,点击了某个功能,进入到该功能模块中

对于应用程序来说,通常不需要在页面中渲染第三方的网页,尤其是在 Electron 中,加载第三方页面可能会导致用户被远程命令执行,因此官方推荐禁用或限制网页跳转

参考文章

https://www.electronjs.org/zh/docs/latest/tutorial/security#13-%E7%A6%81%E7%94%A8%E6%88%96%E9%99%90%E5%88%B6%E7%BD%91%E9%A1%B5%E8%B7%B3%E8%BD%AC

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

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


  • 0x01 简介

  • 0x02 效果展示

  • 0x03 官方安全建议

  • 0x04 哪些行为会导致网页跳转

    • 1. a 标签

    • 2. 表单提交

    • 3. meta 标签自动刷新

    • 4. iframe 加载

    • 5. window.location

    • 6. window.history

    • 7. window.open

    • 8. window.top

  • 0x05 漏洞案例

  • 0x06 总结

  • 0x07 PDF 版 & Github

  • 往期文章


0x02 效果展示

跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

点击链接后

跳转与导航 | Electron 安全

0x03 官方安全建议

官方建议是禁用或限制网页跳转,所谓的限制也就是说选择性地网页跳转,例如允许跳转到自己以及子域名等可控范围内的内容,官方给出代码如下

const { URL } = require('url')
const { app } = require('electron')

app.on('web-contents-created', (event, contents) => {
  contents.on('will-navigate', (event, navigationUrl) => {
    const parsedUrl = new URL(navigationUrl)

    if (parsedUrl.origin !== 'https://example.com') {
      event.preventDefault()
    }
  })
})

官方还专门强调,建议使用Node的解析器来处理URL, 简单的字符串比较有时会出错

0x04 哪些行为会导致网页跳转

既然有了防御代码,我们便可以测试一下,到底哪些行为会进行网页跳转

1. a 标签

跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

点击 a 标签后,成功输出 URL 对象,其中完整内容为

URL {
  href: 'https://www.baidu.com/robots.txt',
  origin: 'https://www.baidu.com',
  protocol: 'https:',
  username: '',
  password: '',
  host: 'www.baidu.com',
  hostname: 'www.baidu.com',
  port: '',
  pathname: '/robots.txt',
  search: '',
  searchParams: URLSearchParams {},
  hash: ''
}

其中 origin 就是我们所谓的同源策略里的源,它包含协议、主机名、端口号

所以官方的防御代码就是验证是不是与 https://example.com 同源的,非同源则直接组织

2. 表单提交

<form action="https://example.com/submit" method="POST">
  <!-- 表单内容 -->
  <input type="text" name="username">
  <button type="submit">提交</button>
</form>

上一节新窗口创建的案例,当然这里 target 设置什么无所谓,我们直接去掉了,关键是 action 属性,这个属性的值造成跳转

跳转与导航 | Electron 安全
跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

出发了跳转和导航事件

3. meta 标签自动刷新

<meta http-equiv="refresh" content="5;url=https://example.com">
跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

5 秒后

跳转与导航 | Electron 安全

成功触发监听

4. iframe 加载

跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

点击按钮

跳转与导航 | Electron 安全

创建一个 iframe 并没有引起主进程的跳转和导航事件,我们修改代码,测试一下按按钮修改 iframesrc 属性

跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

点击按钮

跳转与导航 | Electron 安全

看来 iframesrc 修改不会触发主进程的跳转与导航事件

iframe 加载的内容中通过 window.top.location 修改顶层窗口的 URL

跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

5 秒后

跳转与导航 | Electron 安全

触发导航事件

5. window.location

Window.location 只读属性返回一个 Location 对象,其中包含有关文档当前位置的信息

尽管 Window.location 是一个只读 Location 对象,你仍然可以将字符串赋值给它。这意味着可以在大多数情况下像字符串一样处理 location——location = 'http://www.example.com'——与 location.href = 'http://www.example.com' 等价。

在上一篇文章中,我们介绍了通过 window.open().location 绕过安全限制的手法,其中 location 或者说 location.href 的值就是要导航去的位置

1) location.href

返回当前页面的完整URL字符串,也可以用来设置新的URL以导航到其他页面

window.location.href = "https://www.baidu.com/"
跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

5秒后

跳转与导航 | Electron 安全

触发导航事件

2) location.assign

导航到一个新页面

window.location.assign("https://www.mozilla.org");
跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

5秒后

跳转与导航 | Electron 安全

触发导航事件

3) location.reload

重新加载当前页面

window.location.reload();
跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

5秒后

跳转与导航 | Electron 安全

触发导航事件

4) location.replace

替换当前页面的 URL

window.location.replace('https://example.com')
跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

5秒后

跳转与导航 | Electron 安全

触发导航事件

5) location.search

在 url 后面加上搜索字符串

window.location.search = "test"
跳转与导航 | Electron 安全
跳转与导航 | Electron 安全

5 秒后

跳转与导航 | Electron 安全

6) 其他属性

属性较多,基本上都是 URL 的一部分,如果修改也会导航事件

  • href: 返回当前页面的完整URL字符串,也可以用来设置新的URL以导航到其他页面。
  • protocol: 返回当前URL的协议部分,例如 http:https:
  • host: 返回当前URL的主机名(域名+端口),例如 example.com:8080
  • hostname: 返回当前URL的主机名(不包括端口),例如 example.com
  • port: 返回当前URL的端口号,如果省略则默认端口不会显示
  • pathname: 返回当前URL的路径部分,从根目录开始,例如 /path/to/page.html
  • search: 返回URL的查询字符串部分,从问号 ? 开始,例如 ?key=value&anotherKey=anotherValue
  • hash: 返回URL的哈希片段标识符(锚点),从井号 “#” 开始,例如 #section1
  • origin: 返回URL的起源部分,由协议、主机名和端口组成,例如 http://example.com:80

6. window.history

历史记录属性可以通过其以下几个方法进行导航

  • back(): 导航到历史记录中的上一个页面。
  • forward(): 导航到历史记录中的下一个页面。
  • go(delta): 依据delta参数向前或向后导航。正值表示向前,负值表示向后,0通常不会产生导航效果但可能刷新页面。

这就相当于浏览器的前后按钮了

7. window.open

这部分上一篇文章新窗口创建的部分已经介绍了,会触发导航事件

8. window.top

window.top 是一个JavaScript对象属性,它引用了当前窗口或框架的最顶层窗口(即最高层级的浏览器窗口)

对于没有上层窗口的渲染进程, window === window.top,所以修改  window.top.location 就可以修改当前页面的 url

对于 iframe 等子窗口,使用 window.top.location 可以修改顶层窗口的 URL

0x05 漏洞案例

Masato Kinugawa 曾经在 Discord RCE 的过程中利用了一个导航的漏洞 —— CVE-2020-15174

iframe 中,如果设置 top.location 的地址和 iframe的地址不同源,则不会触发 will-navigate 事件,即导航事件,这显然是一个 bug

https://mksben.l0.cm/2020/10/discord-desktop-rce.html

0x06 总结

网页跳转和导航的触发方法很多,但最终效果几乎都是一致的,就是在当前窗口或新窗口加载页面,在较新的版本中, will-navigate 能够有效地监听和阻断导航行为,开发者可以根据实际情况,考虑禁用或者限制导航行为

0x07 PDF 版 & Github

PDF

https://pan.baidu.com/s/1whO3bFMGfzkzyDWW64TpBw?pwd=kc4x


Github

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

往期文章

跳转与导航 | Electron 安全

有态度,不苟同



原文始发于微信公众号(NOP Team):跳转与导航 | Electron 安全

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

相关文章