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
zotlit-PoC — PoC — l'import de pièces jointes copie des fichiers depuis des chemins locaux non approuvés dans ZotLit (GHSA-4qh7-66xv-h329, CVE-2026-87000, CVSS 5.5). | Kitploit
Outils/GitHubGitHub/squeeze440/zotlit-poc
Analyse des VulnérabilitésExploitationExfiltration de DonnéesCollecte d'InformationsVirtualisation de SécuritéArticles et Recherche
GitHubsqueeze440/zotlit-poc

zotlit-PoC

PoC — l'import de pièces jointes copie des fichiers depuis des chemins locaux non approuvés dans ZotLit (GHSA-4qh7-66xv-h329, CVE-2026-87000, CVSS 5.5).

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

ZotLit : avis de sécurité

Statut CVE : demandé, en attente d'attribution. Cette découverte est publiée sous GHSA-4qh7-66xv-h329. À l'attribution de la CVE, ce dépôt est renommé CVE-YYYY-NNNNN-zotlit-PoC et cette bannière est remplacée par le lien CVE.

ChercheurDostxodjayev Abdullox (@squeeze440)
AvisGHSA-4qh7-66xv-h329
CVSS 3.15.5 (Moyen)
FaiblesseCWE-73, CWE-200

Résumé

Le contrôle externe du nom de fichier ou du chemin dans la fonctionnalité d'import de pièces jointes d'AidenLx ZotLit (aidenlx/zotlit) 1.1.12 permet à un attaquant qui contrôle une bibliothèque Zotero partagée/synchronisée de divulguer des fichiers locaux arbitraires du système de fichiers de la victime dans le coffre Obsidian de la victime via un chemin de pièce jointe linked_file forgé.

Produit

ZotLit — plugin Obsidian pour l'intégration Zotero (aidenlx/zotlit, id du plugin zotlit, version du manifeste 1.1.12)

Version testée

Commit Git 41e60aaa6178629b34f8a42d104e757594b72435 (2026-07-31)

CVSS v3.1 estimé

CVSS:3.1/AV:L/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N — 5.5 (Moyen)

Métriques non évidentes : AV:L — l'exploitation se produit lorsque le processus local Obsidian/zotlit de la victime traite des métadonnées d'élément Zotero fournies par l'attaquant (livrées via une bibliothèque partagée/synchronisée), la même convention utilisée pour les bugs de type « fichier malveillant traité par une application locale », même si la livraison elle-même peut se faire par le réseau (bibliothèque de groupe partagée, fichier d'export envoyé par e-mail). UI:R — la victime doit importer/synchroniser la bibliothèque malveillante dans Zotero et exécuter la fonctionnalité d'import de notes de ZotLit (ou l'intégration d'annotations/citations) sur une note référençant la pièce jointe forgée ; il s'agit d'un usage courant de la fonctionnalité centrale du plugin, activée par défaut (attachment.import vaut true par défaut), et non d'une action inhabituelle. I:N/A:N — cette découverte n'est qu'une primitive de lecture/copie ; aucune traversée de chemin côté destination n'est revendiquée (voir Détails pour une observation connexe mais non vérifiée).

Détails

ZotLit lit les métadonnées des pièces jointes directement depuis la base SQLite de Zotero (ou une bibliothèque synchronisée/partagée), y compris la colonne en texte libre itemAttachments.path, et lui fait entièrement confiance pour résoudre l'emplacement depuis lequel lire une pièce jointe « liée » :

  • packages/db/src/lib/zt-path.ts:62-63 — attachmentAbsPath(), cas "linked-absolute" :

    root@kitploit:~
    case "linked-absolute":
      return parsed.path;
    

    Pour les lignes linkMode: 2 (linked_file) dont le path ne porte pas le placeholder de répertoire de base attachments:, parsed.path est la chaîne brute de la base de données renvoyée telle quelle comme chemin absolu du système de fichiers à lire — aucune liste blanche, aucune confinement au répertoire de données Zotero ou à tout emplacement approuvé par l'utilisateur.

  • packages/db/src/lib/context/zt-template-attach.ts:101-106 — attachmentFilename(), cas "linked-absolute" :

    root@kitploit:~
    case "linked-absolute":
      return basename(path.path);
    

    Le nom de fichier utilisé pour construire la copie dans le coffre est dérivé de ce même chemin contrôlé par l'attaquant via basename(), de sorte que le nom de fichier de destination est influencé par l'attaquant mais sans séparateur de chemin (sûr contre la traversée sur cette branche).

  • apps/obsidian/src/services/note-import/note-parser.ts:403-430 — resolveEmbeddedImage() est invoqué lors de la conversion d'une annotation d'image intégrée d'une note de littérature Zotero en Markdown Obsidian (une action courante et par défaut de la fonctionnalité « Import Note » de ZotLit). Il résout sourcePath = attachmentAbsPath(attachment, ...) et appelle deps.resolveLink({ sourcePath, vaultName: \${attachment.key}-${filename}` })` — mettant en file d'attente une copie de n'importe quel chemin absolu choisi par l'attaquant vers le coffre.

  • apps/obsidian/src/services/attachment-import/service.ts:125-155 — AttachmentImportBatch.resolveLink() met en file d'attente { source: sourcePath, dest: <dossier de pièces jointes du coffre>/<key>-<filename> }, conditionné uniquement par le paramètre attachment.import, dont la valeur par défaut est true (apps/obsidian/src/services/settings/schema.ts:123).

  • apps/obsidian/src/lib/copy-attachments.ts:43-60 — copyAttachment() effectue la lecture+écriture réelle sans aucune validation de chemin : stat(source) puis copyFile(source, dest).

Effet net : un attaquant capable de faire entrer un élément Zotero linked_file (linkMode 2) dans la bibliothèque de la victime — par exemple une bibliothèque de groupe Zotero partagée, un export .rdf/.json/Better BibTeX que la victime importe, ou une bibliothèque synchronisée sur laquelle l'attaquant a un accès en écriture — peut définir le chemin de pièce jointe de cet élément vers n'importe quel fichier du disque de la victime (~/.ssh/id_rsa, stockages d'identifiants de navigateur, autres coffres, fichiers .env, etc.). Dès que la victime exécute l'import de notes de ZotLit (ou affiche/intègre cette annotation) avec le paramètre par défaut attachment.import: true, ZotLit copie silencieusement le contenu de ce fichier dans le coffre Obsidian de la victime sous un nom prévisible (<attachmentKey>-<basename>). Comme les coffres sont couramment synchronisés, commités dans git ou publiés, cela déplace des données que l'attaquant n'aurait jamais pu atteindre autrement vers un emplacement que l'attaquant (ou toute autre personne ayant accès à la cible de synchronisation) peut lire.

Observation connexe non vérifiée (ne fait pas partie du PoC de cette découverte) : la branche sœur "storage" de attachmentFilename() (zt-template-attach.ts:103-104) renvoie le suffixe de chemin brut sans l'appel basename() appliqué aux deux autres branches. La question de savoir si cela est exploitable de manière indépendante dépend de la façon dont le mécanisme de synchronisation de stockage de Zotero nomme les fichiers téléchargés localement, ce qui est hors de ce dépôt et n'a pas été vérifié — signalé ici uniquement comme une lacune de durcissement qu'il vaut la peine de combler par cohérence.

Preuve de concept

Vérification dynamique : les fonctions vulnérables exactes (parseAttachmentPath, attachmentAbsPath, attachmentFilename, copyAttachments/copyAttachment/writeCopy/destMatches, isErrno, reflink) ont été extraites verbatim (fichier:ligne cités ci-dessus, logique inchangée) depuis le code source livré et exécutées directement dans Node, car une installation complète hors ligne de l'espace de travail pnpm n'était pas disponible dans ce bac à sable (chaîne d'outils corepack/pnpm cassée hors ligne). La seule substitution a été de remplacer l'appel au logger LogTape par console.warn — purement cosmétique, aucun effet sur le flux de contrôle. Script : ~/engagements/zotlit/evidence/poc-verify.mjs.

Étapes :

  1. Secret de victime simulé à ~/engagements/zotlit/evidence/victim-disk/id_rsa (contenu factice, clairement marqué comme simulé).
  2. Ligne de pièce jointe Zotero contrôlée par l'attaquant et forgée : { key: "EVILKEY1", path: "<path to victim's id_rsa>", linkMode: 2 } — exactement la forme que getAttachmentByKey renvoie depuis la base de données de Zotero.
  3. Exécution de la vraie attachmentAbsPath() — a résolu la source comme le fichier de la victime, verbatim, sans validation.
  4. Exécution de la vraie attachmentFilename() — a résolu id_rsa comme nom de base de destination d'apparence sûre.
  5. Reproduction de la vraie construction de vaultName depuis note-parser.ts:427 (${key}-${filename}).
  6. Exécution de la vraie copyAttachments() — résultat { copied: 1, skipped: 0, missing: 0 }.
  7. Relecture de fake-vault/attachments/EVILKEY1-id_rsa — le contenu correspond octet pour octet au fichier original de la victime.

Capture d'écran de l'exécution complète (commande + sortie) dans un vrai xterm : ../evidence/poc-run.png

Impact

Un attaquant capable d'influencer le contenu de la bibliothèque Zotero d'une victime (bibliothèque partagée/de groupe, export bibliographique importé, ou bibliothèque synchronisée) peut exfiltrer des fichiers locaux arbitraires que l'utilisateur OS de la victime peut lire — clés SSH, stockages d'identifiants, contenu d'autres coffres, secrets .env/config — vers le coffre Obsidian de la victime, sans invite ni confirmation, dès que la victime utilise la fonctionnalité centrale d'import de notes de ZotLit avec les paramètres par défaut. Les coffres sont couramment synchronisés (Obsidian Sync, git, dossiers cloud) ou publiés, ce qui transforme une primitive de lecture de fichier local en une exposition distante réaliste.

Faiblesses

  • CWE-73 : Contrôle externe du nom de fichier ou du chemin
  • CWE-200 : Exposition d'informations sensibles à un acteur non autorisé

Remédiation

Il est suggéré de confiner les sources de pièces jointes linked_file (linkMode 2) aux emplacements du système de fichiers que la victime a explicitement configurés ou approuvés (par exemple le baseAttachmentPath configuré de Zotero lui-même, ou le répertoire de données de Zotero), et d'inviter l'utilisateur avant de copier automatiquement une pièce jointe liée dont le chemin sort de toute racine attendue. En défense en profondeur, envisagez d'appliquer la même sanitisation par basename() déjà utilisée sur les branches linked-absolute/linked-base de attachmentFilename() à la branche "storage" également, afin qu'aucun chemin de code ne renvoie un fragment de nom de fichier non assaini.

Crédit

Dostxodjayev Abdullox (GitHub : squeeze440)

Canal de signalement

Le signalement privé de vulnérabilités est activé sur aidenlx/zotlit — signalez via un brouillon d'avis de sécurité GitHub (GHSA) sur le dépôt plutôt que via une issue publique.

Télécharger l’outil