Blog / CVE-Erklärungen

CVE-2026-21589: Atlassians Datei-Lesefehler hinter „::“

CVE-2026-21589 ist ein unauthentifizierter Dateizugriff in acht Atlassian-Data-Center-Produkten. So entsteht der Reihenfolgefehler, und so prüfen Sie Ihren Code.

Promotionsstudium in Informationssicherheit abgeschlossenUniversitäre Verteidigung bestanden · Abschließende Dissertationsverteidigung steht noch aus

Eine Bibliothek, acht Produkte, eine Anfrage von Ihren Konfigdateien entfernt

Am 5. Oktober 2026 lieferte Atlassian einen außerplanmäßigen Fix für CVE-2026-21589, einen unauthentifizierten beliebigen Dateizugriff mit CVSS 4.0 9.3. [1] Ein Fehler erreicht acht Data-Center- und Server-Produkte: Jira Software, Jira Service Management, Confluence, Bitbucket, Bamboo, Crowd, Crucible und Fisheye. Sie brechen nicht zufällig gemeinsam. Sie teilen eine Bibliothek, atlassian-plugins-webresource, und der Fehler sitzt darin. Das Advisory nennt den korrigierten Build je Produkt; die Bibliothek selbst ist in 6.0.8 behoben. [1][2]

Atlassian ist bei den Grenzen präzise. Ein Angreifer kann „bestimmte Dateien innerhalb des Web-Application-Root-Verzeichnisses“ lesen, und nur, wenn er den genauen Pfad bereits kennt, ohne Verzeichnislisting. [1] Das klingt eng. Ist es nicht, und warum, ist der Kern dieses Beitrags. Ich habe die Schwachstelle nicht gegen eine Live-Instanz reproduziert; das Folgende beruht auf Atlassians Advisory und der Ursachenanalyse von watchTowr, gelesen am 8. Oktober 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

Der Server hielt „::“ für sicher. Der Angreifer bestimmte, was daraus wurde

Dies ist das Design, dem die Entwickler vertrauten. Web-Resource-URLs tragen einen Ressourcenschlüssel und einen Ressourcennamen. Ein Schrägstrich im Namen würde den Router verwirren, also maskiert ihn die Bibliothek: Jedes „/“ wird beim Eingang zu „::“, und jedes „::“ wird später wieder zu „/“. [2] Diese Kodierung ist vernünftig. Der Fehler liegt nicht in der Kodierung. Der Fehler liegt in der Reihenfolge.

Der Code prüft die eingehende Zeichenkette zuerst auf Traversal, während die Schrägstriche noch als „::“ geschrieben sind. Für diese Prüfung enthält eine Folge wie „..::“ keinen Schrägstrich, wirkt wie ein gewöhnlicher Dateiname und besteht. Erst danach entfernt die Bibliothek die Maskierung, und „..::“ wird zu „../“. [2] Die Komponente, die die Anfrage für sicher hielt, und die Komponente, die das Dateisystem durchlief, sahen zwei verschiedene Zeichenketten. Die Lücke dazwischen gehört dem Angreifer.

Warum ein Dateizugriff in Wahrheit Ihre Identitätsschicht übernimmt

Gehen wir es durch. Der maskierte, traversalähnliche Name besteht die Validierung, wird zurück in echte „../“-Segmente dekodiert und an den Loader übergeben, der aus dem Classpath und dem Web-Application-Root liest. [2] watchTowr berichtet, dass das Lesen im Tomcat-Kontext bleibt, ein Ausstieg nach /etc/passwd ist also nicht möglich. Für einen Angreifer spielt diese Grenze kaum eine Rolle, denn die lesenswerten Dateien liegen schon darin.

Entscheidend ist WEB-INF/classes/crowd.properties. Bei Produkten mit Anbindung an Atlassian Crowd enthält diese Datei den Anwendungsnamen und das Anwendungspasswort für die Kommunikation mit dem Identitätsserver. [2] Ein unauthentifizierter „Datei lesen“-Fehler übergibt damit ein Credential an das System, das Ihre Nutzer verwaltet. watchTowr geht genau diesen Schritt: Datei lesen, das Crowd-Anwendungspasswort nehmen, und schon lesen Sie keine Dateien mehr, sondern sprechen als vertrauenswürdige Anwendung mit der Identitätsschicht. [2]

Das ist der Schritt, den die Schlagzeilen übersprangen. „Liest bestimmte Dateien“ und „übergibt dem Angreifer Ihre Identitätsgeheimnisse“ sind derselbe Fehler, getrennt nur durch das Wissen, welche Datei man anfragt. Die Voraussetzung im Advisory, den genauen Pfad kennen zu müssen, ist real, doch crowd.properties ist kein geheimer Ort. Es ist der Ort, an dem die Datei immer liegt. [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/

Der Patch tauscht zwei Schritte. Stellen Sie sicher, dass genau dieser Tausch deployt ist

Der Fix in atlassian-plugins-webresource 6.0.8 schließt die Lücke, indem Prüfung und Dateisystem dieselbe Zeichenkette sehen: Der Name wird in seine echte Form dekodiert, bevor die Traversal-Prüfung läuft, nicht danach. [2] Das Prinzip lohnt sich beim Namen zu behalten. Erst kanonisieren, dann validieren. Eine Sicherheitsprüfung bedeutet nur etwas, wenn sie genau den Wert inspiziert, der am gefährlichen Sink ankommt. Der Ablauf unten ist diese korrigierte Reihenfolge als Prüfhilfe, keine Kopie von Atlassians Diff.

Für Produktverantwortliche ist die Falle, der Versionsnummer statt dem Artefakt zu glauben. Mehrere dieser Produkte liefern mehr als einen korrigierten Zweig, und ein Rollback-Image, ein Staging-Server oder ein vergessener Crucible-Server kann weiter Bibliothek 6.0.7 laden, während Ihre Notizen „gepatcht“ sagen. [1] Prüfen Sie das jar, das tatsächlich geladen ist, auf der Instanz, die tatsächlich erreichbar ist. Ein korrigierter Checkout auf dem Entwickler-Laptop beweist nichts über den Server im 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

Wie ich diese Form in Code finde, der nichts mit Atlassian zu tun hat

Dieser Fehler handelt eigentlich nicht von Atlassian. Er ist eine Klasse, und die Klasse heißt „validieren, dann transformieren“. Sobald Code einen Wert dekodiert, entmaskiert, normalisiert oder kanonisiert, nachdem er diesen Wert auf Gefahr geprüft hat, haben Sie dieselbe Lücke, ob der Sink ein Dateizugriff, ein SSRF oder eine SQL-Zeichenkette ist. Wenn ich Code prüfe, suche ich per grep zuerst nach einem Dekodierschritt, der stromabwärts einer Validierung auf derselben Variable liegt.

Das Muster unten ist mein Ausgangspunkt. Es fördert die Dekodier- und Sink-Aufrufe zutage; die eigentliche Arbeit ist manuell. Bei jedem Treffer stelle ich eine Frage: Ist die Zeichenkette, die die „..“-Prüfung sah, Byte für Byte dieselbe, die am Dateisystem ankommt? Sitzt eine Transformation dazwischen, prüft die Validierung einen Wert, den es im entscheidenden Moment nicht mehr gibt. Diese Frage findet den Fehler schneller als jede Scanner-Signatur, denn der Scanner gleicht Namen ab und ich gleiche Reihenfolge ab.

# 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 -n "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.

Ist das Ihr Feuer? Für einige von Ihnen ja, heute

Ehrlich zum Ausmaß. Betroffen sind nur selbst gehostete Data-Center- und Server-Installationen. Atlassian sagt, Cloud-Instanzen seien gepatcht und zeigten keine Hinweise auf Ausnutzung. [1] Sind Sie vollständig in Atlassian Cloud, ist das nicht Ihr Vorfall. Hosten Sie eines der acht Produkte selbst und stellen es ins Internet, ist es Ihrer, und die Uhr läuft bereits.

watchTowr veröffentlichte Ursache und Proof of Concept am 6. Oktober und schätzt die exponierte Menge auf den „sechs- bis siebenstelligen Bereich“, allein Confluence mit knapp 700.000 Instanzen nach ihrer Zählung. [2] Rechnen Sie diese Zahl ihnen zu, nicht mir. Unbestritten ist das Tempo. The Hacker News und BleepingComputer berichten, dass Honeypots rund zwei Stunden nach Veröffentlichung der Details Ausnutzungsversuche sahen, bislang überwiegend Fingerprinting und das Absuchen nach Konfigdateien. [3][4] Stand 8. Oktober steht sie nicht im Known-Exploited-Vulnerabilities-Katalog der CISA, was heißt: Es ist früh, nicht still. [3]

Die drei Bedingungen, damit das Ihr Notfall wird, sind also einfach. Sie hosten eines der acht Produkte selbst. Es ist aus dem Internet erreichbar, oder aus einem Netzsegment, dem Sie nicht voll vertrauen. Und es lief im Fenster seit dem 5. Oktober mit einem ungepatchten Bibliotheks-Build. Treffen alle drei zu, ist Patchen Schritt eins, nicht die ganze Arbeit, denn eine Datei, die lesbar war, wurde vielleicht schon gelesen.

Was Sie tun sollten, bevor Sie diesen Tab schließen

Die Liste unten ist die Reihenfolge, in der ich arbeiten würde. Zuerst patchen, denn das Mitigationsfenster misst sich hier in Stunden, nicht in Wochen. [3] Hosten Sie aber selbst und waren exponiert, nehmen Sie an, dass das Crowd-Anwendungspasswort und alles andere unter dem Web-Root gelesen worden sein könnte, und rotieren Sie es. Ein Patch stoppt den nächsten Lesezugriff. Er macht ein Geheimnis, das schon abgeflossen ist, nicht ungeschehen.

Die Zugriffslogs zeigen, ob jemand es versucht hat. Anfragen vor dem Patch an die Web-Resource-Routen mit „::“, „%3a%3a“ oder „..“ im Ressourcennamen sind die Signatur, nach der Sie jagen. Ein Treffer ist kein Beweis für einen erfolgreichen Lesezugriff, aber er sagt Ihnen, welche Instanzen Sie als verdächtig behandeln und welche Geheimnisse Sie zuerst rotieren.

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 -E "/(s|resources|sources)/[^ ]*(::|%3a%3a|\.\.)" access.log

Der Teil, den ein Versionssprung Ihnen nicht sagt

CVE-2026-21589 ist ein klares Beispiel für einen Fehler, den man an der Versionsnummer nicht sieht. Der Fix tauscht zwei interne Schritte, und der einzige Weg, zu wissen, dass Ihr Deployment sicher ist, führt über das laufende Artefakt und den Codepfad, der das Dateisystem erreicht. Das ist die Lücke zwischen „wir haben den Patch eingespielt“ und „wir haben geprüft, dass das Entscheidende geschlossen ist“.

Eine Anfrage vom Rand, durch das Framework, bis zur genauen Zeile zu verfolgen, die entscheidet, was gelesen wird, ist der Kern eines Security Code Reviews, und den „validieren, dann transformieren“-Geruch aus dieser CVE suche ich in Code, der nichts mit Atlassian zu tun hat. Wenn Sie etwas ausliefern, das externe Eingaben in Dateizugriffe, Datenbankabfragen oder interne Anfragen verwandelt, ist das die Grenze, die ich für Sie prüfen würde. Sagen Sie mir, was bei Ihnen läuft, und wir legen den Umfang fest.

Quellen

Soll das auch in Ihrem Produkt geprüft werden?

Security Code-Review
Alle Artikel

08Kontakt

Sie bringen etwas mit Nutzerdaten heraus?

Senden Sie mir eine kurze Beschreibung. Ich antworte innerhalb von drei Tagen mit Rückfragen oder einem Angebotsentwurf; den Preis vereinbaren wir vor Beginn schriftlich.