Top 5 Day Two: Electron Boogaloo - A case for technodiversityDecember 18, 2018 | Vincent Lee
This is the second in our series of Top 5 interesting cases from 2018. Each of these bugs has some element that sets them apart from the approximately 1,400 advisories released by the program this year. This blog actually details multiple bugs in the Electron framework that ended up receiving the same CVE.
Early December 2017, we received a collection of protocol handler related remote code execution vulnerabilities residing in Windows desktop clients of Google Web Designer (ZDI-18-552), Microsoft Teams (ZDI-18-426), Skype (ZDI-18-308), and Slack (ZDI-18-265) from our long time research partner rgod. While they are vastly dissimilar products, they share one thing in common — Electron.js. Electron is a development framework that allows developers to write cross-platform desktop clients using Node.js. It is the cool, new kid on the block of cross-platform desktop application frameworks, or Chromium in disguise.
These four distinct vulnerabilities are all collectively mitigated by a patch from Electron.js known as CVE-2018-1000006. This patch was merged from a downstream product that is not a relevant part of rgod’s submission. Since Electron pulled the patch from an unrelated repo, it appears as though rgod found a bug collision.
This vulnerability is chosen to be one of the top 5 bug of the year because the impact of it goes beyond the aforementioned 4 products. Not long after the publication of the fix, Tomas Lažauninkas (@Wflki) discovered the Exodus wallet application is also affected. On top of this, rgod also discovered identical vulnerable patterns in applications that leveraged the Chromium Embedded Framework, a platform similar to Electron.js. affected the Windows clients of Spotify Music Player (ZDI-18-280) and Amazon Music Player (ZDI-18-215).
Electron.js-based applications can register a custom protocol handler to facilitate the deep linking UX pattern. This allows users to click on a custom application URI in the browser and cause the corresponding application to launch and display context-aware content. An attacker can craft a custom URI with arbitrary command line arguments and inject embedded Chromium command line options to influence the program flow or launch condition of the application.
Some Chromium options are quite dangerous. For example the
--gpu-launcher= option will create a process with the provided command. Many publicly available PoC had exploited this command line option. In rgod’s submission for Microsoft Team (ZDI-18-426), he had demonstrated this technique with the following PoC:
However, we have not seen any public PoC using the exploit techniques demonstrated by rgod in his other submissions. In the submission for ZDI-18-552 affecting Google Web Designer, he had exploited three other command line options to inject a
.hta HTML Application file into the log file. The log file is controlled by the attacker and placed in the startup directory of the victim’s machine:
When the victim restarts their computer, the
suntzu.hta will be executed as a startup program and the calculator app will be launched.
In the submission of ZDI-18-308 affecting Microsoft Skype, he had demonstrated another exploit technique:
--browser-subprocess-path= Chromium command line option allows the user to specify the path to the executable file for the renderer and plugin subprocesses. In this PoC, rgod had demonstrated the payload file can also be stored on a network UNC path. This exploit technique can potentially throw a wrench into some Endpoint Detection and Response (EDR) software.
In his submission for Slack (ZDI-18-265), he pointed out an existing instance of Slack would stop the exploit from running. The ‘--user-data-dir=' option was added to instruct Slack to use different user profiles and cause Slack to launch a run the exploit even if there is an active instance running on the victim’s machine:
Heart of the issue
Electron mitigated these bugs by blacklisting a list of Chromium related command line options. While this does make these particular bugs unexploitable, the root cause of the problem remains unpatched. When an application calls the Electron.js API
app.setAsDefaultProtocolClient() to register a custom URI for its Windows client, Electron.js creates a new registry key in Windows. Below is how Electron.js registered for the custom protocol in the vulnerable version of the Slack Windows client.
According to the Microsoft documentation, this registration will set
slack.exe as the handler for the custom
slack:// URI scheme. The entire URI will replace the “%1” string and be passed to the handler as a command line option. Microsoft has documented potential security pitfalls of the simple string replacement.
Not only did the developers of Electron.js not register the handler in a secure fashion by default, they also did not communicate the potential security issue raised in Microsoft’s documentation. We can see that the latest release version of Electron.js still registers the handler in an insecure manner by default and only includes the briefest of notes that it may be “written by unprivileged users.”