Electron API滥用:攻击者的首选
2021年2月16日 - 作者:Luca Carettoni, Lorenzo Stella
ElectronJs正日益变得更加安全。随着Electron 12稳定版的即将发布,上下文隔离和其他安全设置计划默认启用,这似乎结束了该框架某种程度上应得的系统性不安全声誉。
看到如此显著和切实的进展,我们感到自豪。过去几年,我们致力于通过研究不同的攻击面来帮助开发人员保护他们的应用程序:
- 现代炼金术:将XSS转化为RCE
- Electron Windows协议处理程序MITM/RCE(绕过CVE-2018-1000006修复)
- 通过不安全的预加载颠覆Electron应用
- 签名验证绕过导致Electron-Updater中的RCE
正如Electron开发团队在v11稳定版中确认的那样,他们计划大约每季度发布新主要版本的Electron(包括新版本的Chromium、Node和V8)。如此雄心勃勃的版本计划也将增加新引入API的数量和频率,计划中的破坏性更改以及后续版本中的安全细微差别。虽然新功能当然是可取的,但新框架的API也可能暴露强大的操作系统功能接口,开发人员可能会或多或少无意中启用这些接口,因为他们被Electron提供的语法糖所吸引。
这些接口可能通过预加载或不安全配置暴露给渲染器,并可能被攻击者滥用,超出其原始目的。一个臭名昭著的例子是openExternal
。
Shell的openExternal()
允许使用桌面的本机实用程序打开给定的外部协议URI。例如,在macOS上,此函数类似于open
终端命令实用程序,并将根据URI和文件类型关联打开特定应用程序。当openExternal
与不受信任的内容一起使用时,它可以被利用来执行任意命令,如下例所示:
|
|
类似地,shell.openPath(path)
可用于以桌面的默认方式打开给定文件。
从攻击者的角度来看,Electron特定的API通常是最容易获得远程代码执行、对主机文件系统的读写访问或泄漏敏感用户数据的途径。在渲染器中运行的恶意JavaScript通常可以使用这些原语来颠覆应用程序。
考虑到这一点,我们收集了一个非全面的API列表,这些API在我们过去的参与中被成功滥用。当这些API暴露给渲染器中的用户时,它们可以显著影响基于Electron的应用程序的安全态势,并促进nodeIntegration / sandbox绕过。
Remote.app
remote模块为渲染器进程提供了一种访问通常仅在主进程中可用的API的方式。在Electron中,GUI相关模块(如dialog、menu等)仅在主进程中可用,而不在渲染器进程中。为了从渲染器进程中使用它们,需要remote模块来向主进程发送进程间消息。
虽然这似乎非常有用,但这个API一直是性能和安全性问题的根源。因此,remote模块将在Electron 12中弃用,并最终在Electron 14中移除。
尽管有警告和大量关于该主题的文章,我们已经看到一些应用程序将Remote.app暴露给渲染器。app对象控制着完整的应用程序事件生命周期,它基本上是每个基于Electron的应用程序的核心。
该对象暴露的许多函数可以很容易地被滥用,包括但不限于:
app.relaunch([options])
在当前实例退出时重新启动应用程序。app.setAppLogsPath([path])
设置或创建应用程序日志的目录,然后可以使用app.getPath()
或app.setPath(pathName, newPath)
进行操作。app.setAsDefaultProtocolClient(protocol[, path, args])
将当前可执行文件设置为指定协议的默认处理程序。app.setUserTasks(tasks)
将任务添加到Jump List的Tasks类别中(仅限Windows)。app.importCertificate(options, callback)
将pkcs12格式的证书导入平台证书存储(仅限Linux)。app.moveToApplicationsFolder([options])
将应用程序移动到默认的Application文件夹(仅限Mac)。app.setJumpList(categories)
设置或移除应用程序的自定义Jump List(仅限Windows)。app.setLoginItemSettings(settings)
设置登录时启动的可执行文件及其选项(仅限Mac、Windows)。
以第一个函数为例,app.relaunch([options])
可用于在当前实例退出时重新启动应用程序。使用此原语,可以指定一组选项,包括一个execPath
属性,该属性将用于重新启动而不是当前应用程序,以及一个自定义的args
数组,该数组将作为命令行参数传递。攻击者可以轻松利用此功能执行任意命令。
|
|
请注意,relaunch
方法单独执行时不会退出应用程序,并且还需要在调用该方法后调用app.quit()
或app.exit()
以使应用程序重新启动。
systemPreferences
另一个经常导出的模块是systemPreferences
。此API用于获取系统偏好设置并发出系统事件,因此可以被滥用来泄漏用户行为及其操作系统活动和使用模式的多个信息。通过该模块减去的元数据随后可以被滥用来发起针对性攻击。
subscribeNotification, subscribeWorkspaceNotification
这些方法可用于订阅macOS的本机通知。在底层,此API订阅了NSDistributedNotificationCenter
。在macOS Catalina之前,可以通过调用CFNotificationCenterAddObserver
函数并为name参数指定nil(对应于subscribeNotification
的event参数)来注册全局监听器并接收所有分布式通知。指定的回调将在任何应用程序广播分布式通知时被调用。在macOS Catalina或Big Sur发布后,对于沙盒应用程序,仍然可以通过按名称注册接收任何通知来全局嗅探分布式通知。因此,可以嗅探许多敏感事件,包括但不限于:
- 屏幕锁定/解锁
- 屏幕保护程序启动/停止
- 蓝牙活动/HID设备
- 卷(USB等)挂载/卸载
- 网络活动
- 用户文件下载
- 新安装的应用程序
- 打开的源代码文件
- 使用中的应用程序
- 加载的内核扩展
- …以及来自已安装应用程序的更多信息,包括其中的敏感信息。分布式通知始终是公开的,将敏感信息放入其中从来都是不正确的。
最新的NSDistributedNotificationCenter
API似乎在Big Sur和沙盒应用程序中也存在间歇性问题,因此我们预计未来会有更多的破坏性更改。
getUserDefault, setUserDefault
getUserDefault
函数返回NSUserDefaults
中键的值,这是一个macOS简单存储类,提供了与默认系统交互的编程接口。此systemPreferences
方法可以被滥用来返回应用程序或全局的偏好设置。攻击者可能滥用该API来检索敏感信息,包括用户的位置和文件系统资源。作为演示,getUserDefault
可用于获取目标应用程序用户的个人详细信息:
用户文件系统上的最近位置
|
|
用户选择的