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é.

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

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-34213 — Un utilisateur Docmost à faibles privilèges pourrait fournir un `attachmentId` de victime au point de terminaison de téléchargement générique et écraser la pièce jointe stockée d'une autre page dans le même espace de travail. | Kitploit
Outils/GitHubGitHub/0xmrma/cve-2026-34213
Analyse des VulnérabilitésExploitation d'Applications WebTests d'IntrusionArticles et RechercheApprentissage et Éducation
GitHub0xmrma/cve-2026-34213

CVE-2026-34213

Un utilisateur Docmost à faibles privilèges pourrait fournir un `attachmentId` de victime au point de terminaison de téléchargement générique et écraser la pièce jointe stockée d'une autre page dans le même espace de travail.

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

Un utilisateur Docmost à faibles privilèges pourrait fournir un attachmentId victime au point de terminaison de téléversement générique et écraser la pièce jointe stockée d'une autre page dans le même espace de travail.

Introduction

J'ai identifié, divulgué de manière responsable et reproduit un défaut d'autorisation de Haute gravité dans Docmost, la plateforme collaborative de documentation open‑source.

Le site officiel de Docmost la présente comme un wiki sur site prêt pour l'entreprise avec 3M+ téléchargements, et affirme qu'elle est utilisée par des équipes d'organisations dont Vilnius City, Bechtle, le Gouvernement australien, la Croix‑Rouge et ETS Québec.

Le bogue vivait dans le chemin générique de téléversement de fichiers que Docmost utilise également pour les flux de sauvegarde/mise à jour de diagrammes.

J'examinais ce code avec une question très spécifique en tête :

Que se passe‑t‑il si le point de terminaison de téléversement prouve l'accès en modification sur une page, mais que la cible d'écrasement est sélectionnée avec un identifiant de pièce jointe distinct contrôlé par l'utilisateur ?

Dans ce cas, cette question a directement conduit à une véritable défaillance de liaison d'objet.

Docmost permettait à un appelant d'envoyer :

  • un pageId pour une page qu'il était autorisé à modifier, et
  • un attachmentId appartenant à une page différente dans le même espace de travail

Le serveur effectuait bien un contrôle de cohérence d'écrasement, mais la garde utilisait la mauvaise logique booléenne.

Cela signifiait que la requête pouvait passer l'autorisation et écraser la pièce jointe victime quand même.

Ce problème est devenu CVE-2026-34213.

Docmost : docmost/docmost
Avis : GHSA-89fp-2hch-j9gp
CVE : CVE-2026-34213
Corrigé dans : v0.71.0

photo0 ---

Chaîne d'attaque

pageId contrôlé par l'attaquant avec accès en modification -> victim attachmentId contrôlé par l'attaquant -> garde d'écrasement défaillante traite l'écrasement inter‑pages comme valide -> chemin de stockage reconstruit à partir du victim attachmentId -> les octets de l'attaquant remplacent le fichier victime -> la page victime continue de servir la pièce jointe modifiée


Ce que fait cette partie de Docmost

Docmost stocke les pièces jointes téléversées sous forme d'enregistrements en base de données plus des fichiers de sauvegarde dans le stockage.

Pour les téléversements normaux, le serveur crée un nouvel identifiant de pièce jointe et écrit un nouveau fichier.

Pour les flux de sauvegarde/mise à jour de diagrammes, cependant, le client réutilise intentionnellement un attachmentId existant afin que le même fichier de diagramme puisse être mis à jour sur place au lieu de générer un tout nouvel enregistrement de pièce jointe à chaque fois.

Ce comportement est légitime en soi.

Le problème est qu'il crée un chemin à haut risque :

  • une entrée identifie la page en cours d'autorisation
  • une autre entrée identifie la pièce jointe en cours d'écrasement

Chaque fois qu'un point de terminaison mélange ces deux responsabilités, l'implémentation doit les lier exactement.

Docmost ne l'a pas fait.


Pourquoi cette surface méritait d'être examinée

Les points de terminaison mixtes création/mise à jour sont des endroits courants pour les bogues d'autorisation.

La raison est simple :

  • les flux de création sont généralement autorisés par rapport à l'objet conteneur
  • les flux de mise à jour sont généralement autorisés par rapport à l'enregistrement existant
  • si un point de terminaison essaie de faire les deux, il est facile de valider la mauvaise chose en premier et de traiter le deuxième identifiant comme « simple métadonnée »

C'est exactement le schéma ici.

POST /api/files/upload validait que l'appelant pouvait modifier la page nommée par pageId.

Mais si attachmentId était également fourni, le serveur basculait vers un chemin d'écrasement et sélectionnait un enregistrement de pièce jointe existant séparément.

Cela posait la question de sécurité critique :

le chemin d'écrasement prouve‑t‑il que la pièce jointe sélectionnée appartient bien à la page autorisée ?

La réponse dans les versions vulnérables était non.


Cause racine

La cause racine était un contournement d'autorisation via une clé contrôlée par l'utilisateur, combiné à un bogue de logique booléenne dans la garde d'écrasement.

Le flux vulnérable ressemblait à ceci :

  1. AttachmentController.uploadFile() lisait pageId à partir des données de formulaire multipart.
  2. Il chargeait cette page et appelait validateCanEdit(page, user).
  3. Il acceptait séparément un attachmentId optionnel depuis la même requête.
  4. AttachmentService.uploadFile() chargeait la pièce jointe existante via cet identifiant fourni par l'attaquant.
  5. La garde d'écrasement tentait de vérifier que la pièce jointe existante correspondait à la page autorisée.
  6. La garde utilisait && au lieu de rejeter sur toute non‑correspondance.

La garde vulnérable était :

if (
  existingAttachment.pageId !== pageId &&
  existingAttachment.fileExt !== preparedFile.fileExtension &&
  existingAttachment.workspaceId !== workspaceId
) {
  throw new BadRequestException("File attachment does not match");
}

Cette condition ne rejetait la requête que si :

  • l'identifiant de page ne correspondait pas, et
  • l'extension de fichier ne correspondait pas, et
  • l'identifiant d'espace de travail ne correspondait pas

tous en même temps.

C'est l'inverse de ce qu'une garde d'écrasement devrait faire.

Dans le cas d'attaque réel, l'attaquant restait intentionnellement dans le même espace de travail.

Donc :

  • existingAttachment.workspaceId !== workspaceId était false

Une fois que cet opérande devenait false, toute la condition && s'évaluait à false, même si la pièce jointe appartenait à une page différente.

Ainsi, le serveur traitait un écrasement inter‑pages comme valide.

C'était la première moitié du bogue.

La seconde moitié est ce qui rend l'impact réel.

Après la vérification, le service reconstruisait le chemin de stockage de destination en utilisant le attachmentId et le nom de fichier fournis par l'attaquant :

const filePath =
  `${getAttachmentFolderPath(AttachmentType.File, workspaceId)}/` +
  `${attachmentId}/${preparedFile.fileName}`;

Ensuite, sur le chemin de mise à jour, Docmost ne mettait à jour que les métadonnées mutables telles que :

  • fileSize
  • updatedAt

Il ne reliait pas la propriété à la page de l'attaquant.

Ainsi, la page victime continuait de pointer vers le même enregistrement de pièce jointe et le même identifiant de pièce jointe. Seuls les octets du fichier sous‑jacent changeaient.

C'est pourquoi ce n'était pas une simple non‑correspondance inoffensive.

C'était une primitive d'écrasement persistant non autorisé.


Pourquoi c'est un problème de sécurité, pas seulement une erreur de logique

Ce n'était pas un bogue cosmétique ni un problème de collision de noms de fichiers.

L'attaquant n'avait pas besoin d'une condition de course. L'attaquant n'avait pas besoin de deviner un chemin aléatoire. L'attaquant n'avait pas besoin d'accès en écriture à la page victime.

Il avait seulement besoin :

  • d'un accès en lecture pour apprendre une référence de pièce jointe victime, et
  • d'un accès en écriture à n'importe quelle autre page dans le même espace de travail
Télécharger l’outil