Blog / CVE expliquées

CVE-2026-21589 : la lecture de fichiers d’Atlassian qui se cache derrière ::

CVE-2026-21589 est une lecture de fichiers sans authentification dans huit produits Data Center d’Atlassian. Voici l’erreur d’ordre qui en est la cause, et comment vérifier votre propre code.

Études doctorales en sécurité de l’information achevéesSoutenance universitaire réussie · Soutenance finale de thèse à venir

Une bibliothèque, huit produits, une seule requête jusqu’à vos fichiers de configuration

Aucune connexion. Et pourtant, la réponse est revenue. Sur une instance reliée à Atlassian Crowd, c’est un 200 OK qui contient un mot de passe, obtenu par une requête sans la moindre authentification. Le 5 octobre 2026, Atlassian a publié un correctif hors cycle pour CVE-2026-21589, une lecture arbitraire de fichiers sans authentification notée 9,3 en CVSS 4.0. [1] Une seule faille touche huit produits Data Center et Server : Jira Software, Jira Service Management, Confluence, Bitbucket, Bamboo, Crowd, Crucible et Fisheye. Ils ne cèdent pas tous par hasard. Ils partagent une bibliothèque, atlassian-plugins-webresource, et c’est là que se trouve le bogue. L’avis indique la version corrigée de chaque produit ; la bibliothèque elle-même est corrigée en 6.0.8. [1][2]

Atlassian prend soin d’en préciser les limites. Un attaquant peut lire « des fichiers précis situés dans le répertoire racine de l’application web », et seulement s’il en connaît déjà le chemin exact, sans listage de répertoire. [1] Cela paraît restreint. Ce n’est pas le cas, et c’est justement tout l’objet de cet article. Je n’ai pas reproduit cette faille sur une instance réelle ; ce qui suit repose sur l’avis d’Atlassian et sur l’analyse de la cause racine publiée par watchTowr, consultés le 8 octobre 2026. [1][2]

// atlassian-plugins-webresource, before 6.0.8
escapeSlashes(String string)   { return string.replaceAll("/", "::"); }
unescapeSlashes(String string) { return string.replaceAll("::", "/"); }

// How a web-resource name is handled on the way in:
resourceName                       // attacker-controlled
  -> check for ".." / "/" traversal   // sees "..::", no slash -> looks safe
  -> unescapeSlashes(resourceName)    // "..::"  becomes  "../"
  -> load file relative to web root   // traversal now active

Le serveur croyait :: inoffensif. L’attaquant contrôlait ce qu’il devenait

Voici la conception à laquelle les développeurs se sont fiés. Les URL des web-resources portent une clé de ressource et un nom de ressource. Une barre oblique dans ce nom perturberait le routeur, donc la bibliothèque l’échappe : chaque « / » devient « :: » à l’entrée, et chaque « :: » redevient « / » plus tard. [2] Ce type d’encodage est raisonnable. Le bogue n’est pas l’encodage. Le bogue, c’est l’ordre.

Le code vérifie d’abord la présence d’un parcours de répertoires dans la chaîne entrante, alors que les barres sont encore écrites « :: ». Pour ce contrôle, une séquence comme « ..:: » ne contient aucune barre : elle ressemble à un nom de fichier ordinaire et passe. Ce n’est qu’ensuite que la bibliothèque désechappe la chaîne, et « ..:: » devient « ../ ». [2] Le composant qui a jugé la requête sûre et celui qui a parcouru le système de fichiers regardaient deux chaînes différentes. L’attaquant maîtrise l’écart entre les deux.

Pourquoi une lecture de fichiers revient à prendre le contrôle de votre couche d’identité

Déroulons le scénario. Le nom échappé, qui ressemble à un parcours de répertoires, franchit la validation, est décodé en vrais segments « ../ », puis transmis au chargeur qui lit dans le classpath et la racine de l’application web. [2] watchTowr indique que la lecture reste confinée au contexte Tomcat : impossible de remonter jusqu’à /etc/passwd. Pour un attaquant, cette limite compte à peine, car les fichiers qui valent la peine d’être lus se trouvent déjà à l’intérieur.

Celui qui compte est WEB-INF/classes/crowd.properties. Sur les produits reliés à Atlassian Crowd, ce fichier contient le nom de l’application et le mot de passe d’application utilisé pour dialoguer avec le serveur d’identité. [2] Un bogue de « lecture de fichier » sans authentification livre alors un identifiant du système qui gère vos utilisateurs. watchTowr décrit précisément cette étape : on lit le fichier, on récupère le mot de passe d’application Crowd, et l’on ne lit plus des fichiers, on parle à la couche d’identité en tant qu’application de confiance. [2]

C’est l’étape que les gros titres ont passée sous silence. « Lit des fichiers précis » et « livre vos secrets d’identité à un attaquant » sont le même bogue, à ceci près qu’il faut savoir quel fichier demander. La précondition de l’avis, à savoir connaître le chemin exact, est réelle, mais crowd.properties n’est pas un emplacement secret. C’est là que ce fichier se trouve toujours. [1][2]

# WEB-INF/classes/crowd.properties  (illustrative keys, not real values)
application.name       = my-confluence
application.password   = <shared secret to the Crowd identity server>
crowd.server.url       = https://id.example.internal/crowd/services/
crowd.base.url         = https://id.example.internal/crowd/

Le correctif inverse deux étapes. Vérifiez que c’est bien ce que vous avez déployé

Le correctif d’atlassian-plugins-webresource 6.0.8 comble l’écart en faisant voir la même chaîne au contrôle et au système de fichiers : le nom est décodé dans sa forme réelle avant le contrôle de parcours, et non après. [2] Le principe mérite d’être retenu tel quel : canonicaliser d’abord, valider ensuite. Un contrôle de sécurité n’a de sens que s’il examine exactement la valeur qui atteint le point dangereux. Le flux ci-dessous présente cet ordre corrigé comme aide à la revue, pas comme copie du diff d’Atlassian.

Pour un responsable produit, le piège consiste à se fier au numéro de version plutôt qu’à l’artefact. Plusieurs de ces produits publient plus d’une branche corrigée, et une image de retour arrière, un serveur de préproduction ou un Crucible oublié peuvent encore charger la bibliothèque 6.0.7 alors que vos notes indiquent « corrigé ». [1] Vérifiez le jar réellement chargé, sur l’instance réellement accessible. Une copie corrigée sur le portable d’un développeur ne prouve rien sur le serveur exposé à Internet.

// The fix, as a principle (not Atlassian's exact diff):
// decode to the real value FIRST, then validate THAT value.
resourceName
  -> unescapeSlashes(resourceName)    // "..::"  becomes  "../"  up front
  -> check the decoded value for ".." traversal   // now the check sees it
  -> reject, or load file relative to web root

Comment je repérerais ce schéma dans un code qui n’est pas celui d’Atlassian

Ce bogue ne concerne pas vraiment Atlassian. C’est une classe de défauts, et cette classe s’appelle « valider, puis transformer ». Chaque fois qu’un code décode, désechappe, normalise ou canonicalise une valeur après l’avoir contrôlée, il présente le même trou, que la destination soit une lecture de fichier, une SSRF ou une requête SQL. Quand je fais une revue de code, la première chose que je cherche avec grep est une étape de décodage située en aval d’une étape de validation sur la même variable.

Le motif ci-dessous est mon point de départ. Il fait ressortir les appels de décodage et les destinations ; le vrai travail est manuel. Pour chaque résultat, je me pose une seule question : la chaîne examinée par le contrôle « .. » est-elle, octet pour octet, celle qui atteint le système de fichiers ? Si une transformation s’intercale, le contrôle examine une valeur qui n’existe plus au moment où cela compte. Cette question trouve ce bogue plus vite que n’importe quelle signature de scanner, parce que le scanner compare des noms et moi, je compare l’ordre.

# Smell to hunt: a decode/normalise step that runs AFTER the path check,
# on the same variable. Start broad, then read each hit by hand.
rg -ni "replaceAll|URLDecoder|decode|unescape|normalize|canonical" \
   --glob '!**/test/**'

# The one question that confirms the bug:
#   is the string that reaches the file sink byte-for-byte the string
#   the ".." check inspected? If a transform sits between them, it is vulnerable.

Est-ce votre incendie ? Pour certains d’entre vous, oui, aujourd’hui

Soyons honnêtes sur l’ampleur. Cela ne concerne que les installations Data Center et Server hébergées par vos soins. Atlassian indique que les instances Cloud ont été corrigées et ne montre aucune trace d’exploitation de ce côté. [1] Si vous êtes entièrement sur Atlassian Cloud, ce n’est pas votre incident. Si vous hébergez vous-même l’un des huit produits et l’exposez à Internet, c’en est un, et le compte à rebours a déjà commencé.

watchTowr a publié la cause racine et une preuve de concept le 6 octobre et situe la population exposée « dans une fourchette à six ou sept chiffres », avec un peu moins de 700 000 instances Confluence à elles seules selon son décompte. [2] Prenez ce chiffre comme le leur, pas comme le mien. Ce qui ne fait pas débat, c’est la vitesse. The Hacker News et BleepingComputer rapportent que des honeypots ont observé des tentatives d’exploitation environ deux heures après la publication des détails, pour l’instant surtout de l’identification de systèmes et du balayage à la recherche de fichiers de configuration. [3][4] Mise à jour du 18 octobre : la CISA a confirmé une exploitation active en ajoutant cette CVE à son catalogue des vulnérabilités exploitées connues le 15 octobre, avec une échéance fédérale de correction fixée à aujourd’hui. [5]

Les trois conditions pour que ce soit votre urgence sont donc simples. Vous hébergez vous-même l’un des huit produits. Il est accessible depuis Internet, ou depuis un segment de réseau auquel vous ne faites pas entièrement confiance. Et il a fait tourner une version non corrigée de la bibliothèque pendant la période qui a suivi le 5 octobre. Si les trois sont réunies, corriger est la première étape, pas tout le travail, car un fichier lisible a peut-être déjà été lu.

Ce qu’il faut faire avant de fermer cet onglet

La liste ci-dessous suit l’ordre dans lequel je travaillerais. D’abord corriger, car la fenêtre de mitigation se compte ici en heures, pas en semaines. [3] Mais si vous hébergez le produit vous-même et avez été exposé, partez du principe que le mot de passe d’application Crowd et tout autre élément situé sous la racine web ont pu être lus, et renouvelez-les. Un correctif empêche la lecture suivante. Il ne rattrape pas un secret qui a déjà fuité.

C’est dans les journaux d’accès que vous saurez si quelqu’un a essayé. Les requêtes antérieures au correctif vers les routes web-resource contenant « :: », « %3a%3a » ou « .. » dans le nom de ressource sont la signature à rechercher. Une correspondance ne prouve pas qu’une lecture a réussi, mais elle vous indique quelles instances traiter comme suspectes et quels secrets renouveler en priorité.

Patch and verify (in this order):
  [ ] List every self-hosted install: Jira, JSM, Confluence, Bitbucket,
      Bamboo, Crowd, Crucible, Fisheye.
  [ ] Confirm the build that is RUNNING, not the one in your notes.
  [ ] Patch each product to its fixed version from the advisory [1].
  [ ] Cannot patch yet? Apply Atlassian's WAF / RewriteValve mitigation [1].

If you were exposed and unpatched, assume read, then rotate:
  [ ] The Crowd application password in crowd.properties.
  [ ] Any other secret stored under the web application root.

Hunt the access logs for pre-patch probing:
  grep -iE "/(s|resources|sources)/[^ ]*(::|%3a%3a|\.\.)" access.log

Ce qu’une montée de version ne vous dira pas

CVE-2026-21589 est un exemple net de bogue invisible dans le numéro de version. Le correctif inverse deux étapes internes, et la seule façon de savoir que votre déploiement est sûr est d’examiner l’artefact qui tourne et le chemin de code qui atteint le système de fichiers. C’est tout l’écart entre « nous avons appliqué le correctif » et « nous avons vérifié que ce qui compte est bien fermé ».

Suivre une requête depuis la périphérie, à travers le framework, jusqu’à la ligne exacte qui décide de ce qui est lu, c’est le cœur d’une revue de code sécurité ; et le schéma « valider, puis transformer » de cette CVE est une chose que je recherche dans du code qui n’a rien à voir avec Atlassian. Si vous livrez quelque chose qui transforme des entrées externes en accès à des fichiers, en requêtes de base de données ou en appels internes, c’est cette frontière que je vérifierais pour vous. Dites-moi ce que vous faites tourner et nous cadrerons la mission.

Sources

Besoin de vérifier ce point dans votre propre produit ?

Revue de code sécurité

Vous voulez apprendre à trouver vous-même ce type de vulnérabilité ?

Formation individuelle à la revue de code sécurisé
Tous les articles

08Contact

Vous livrez un produit qui traite des données d’utilisateurs ?

Envoyez-moi un bref descriptif. Je réponds sous trois jours avec des questions ou une première proposition, et le prix est fixé par écrit avant le démarrage.