XSS to Reverse Shell: Only a Sith Deals in Absolutes

Oct 9, 2021

4 mins read

Recently I stumbled across a thread on Reddit r/AskNetsec


Now, without looking at the post: What do you think the answers looked like?

If you guessed a lot of people saying “You don’t” or “You can’t”, give yourself a pat on the back because you guessed correctly!

Now, it’s specific definitive assertions like “don’t” or “can’t” I take extreme issue with: Only a Sith Deals in Absolutes. This phrase (shamelessly stolen from Star Wars) refers to the fact that only the Sith deal and act based on absolute values, without thinking and without grey areas.

Let’s make some generalizations about why the phrases “can’t” and “don’t” aggravate me:

  1. With the right imagination and creativity any idea should seem possible, even if it isn’t actually possible.
  2. Finding out if it is “possible” is an exercise of the mind, not something you should ever give a definitive answer about.
  3. Stating that something “can’t” be done with a computer is probably the easiest way for time to prove you wrong. Computers are awesome.

So, without further ado we’re going to demonstrate how to get a netcat reverse shell with Cross Site Scripting ✔


Traditional XSS in a web browser is very hard to use to achieve remote code execution due to browser sandboxing and various security measures. However, there’s this new thing called Electron which is basically just a Chromium based web browser. Programs like Discord, Slack, Microsoft Teams, etc… all run on Electron.

In fact, many of your desktop apps actually use Electron behind the scenes because they offer all of the benefits of a full web browser as well as an integration with a node.js runtime which allows the application to do things a standard web browser can’t do.

As a web browser, a Cross Site Scripting (XSS) vulnerability is no different in how it’s discovered, but if the Electron application takes advantage of these special features it can easily become vulnerable to remote code execution.

A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump out of the renderer process and execute code on the user’s computer. Cross-site-scripting attacks are fairly common - and while an issue, their power is usually limited to messing with the website that they are executed on. Disabling Node.js integration helps prevent an XSS from being escalated into a so-called “Remote Code Execution” (RCE) attack.


XSS in Electron

For this demo I’m going to just take a standard electron app boilerplate and add in a little functionality that lets a user “Sign the Guestbook” which is vulnerable to XSS.



Since our boilerplate Electron app has the following default configuration, nodeIntegration is enabled.

  const mainWindow = createWindow("main", {
    width: 1000,
    height: 600,
    webPreferences: {
      // Two properties below are here for demo purposes, and are
      // security hazard. Make sure you know what you're doing
      // in your production app.
      nodeIntegration: true,
      contextIsolation: false,
      // Spectron needs access to remote module
      enableRemoteModule: env.name === "test"

This means that we can utilizes functionality from NodeJS in our XSS payload including require()

The builtin require function is the easiest way to include modules that exist in separate files. The basic functionality of require is that it reads a JavaScript file, executes the file, and then proceeds to return the exports object.

Knowing this, we can simply require() a module that allows us to call external programs and execute code. For this example I’m using the following payload:

const {shell} = require('electron');


In this example I’m “popping calc”, or proving that I can achieve executing code by opening the windows calculator app.

Replacing calc.exe with any of the PayloadAllTheThings reverse shell payloads would complete the scope of “get a netcat reverse shell with Cross Site Scripting”


Stop listening to people who tell you that something can’t be done with a computer and go do it anyways.

Sharing is caring!