
Das writeToFile-Hilfsprogramm von Consul Template öffnete ein vom Operator angegebenes Ziel direkt und folgte verlinkten Pfadkomponenten, sodass gerenderte Ausgabe das vorgesehene Verzeichnis verlassen und eine bereits vorhandene Datei überschreiben konnte.
Der writeToFile-Helper von Consul Template öffnete ein vom Betreiber angegebenes Ziel direkt und folgte verlinkten Pfadkomponenten, wodurch gerenderte Ausgaben das vorgesehene Verzeichnis verlassen und eine bereits vorhandene Datei überschreiben konnten.
Ich fand dieses Problem bei der Überprüfung von HashiCorp Consul Template, mit einer direkten Dateisystem-Sicherheitsfrage im Hinterkopf:
Wenn writeToFile einen Pfad erhält, der scheinbar innerhalb des vorgesehenen Verzeichnisses liegt, wird dann geprüft, wohin das Dateisystem die Daten tatsächlich schreibt?
In diesem Fall lautete die Antwort nein.
Der Template-Helper writeToFile öffnete den endgültigen, vom Benutzer bereitgestellten Pfad direkt über os.Create() oder os.OpenFile().
Diese Operationen folgten symbolischen Links, Directory Junctions und gleichwertigen Dateisystem-Umleitungen, die bereits im Zielpfad vorhanden waren.
Das bedeutete, dass die Pfadzeichenkette innerhalb des vom Betreiber vorgesehenen Wurzelverzeichnisses bleiben konnte, während der tatsächliche Schreibvorgang woanders landete.
In meinem kontrollierten Proof of Concept leitete ein verlinktes Elternverzeichnis die gerenderte Ausgabe außerhalb des vorgesehenen Verzeichnisbaums um und führte dazu, dass eine bereits vorhandene Zieldatei überschrieben wurde.
Dieses Problem wurde zu CVE-2026-14361.
HashiCorp-Bulletin: HCSEC-2026-20
IBM-Bulletin: CVE-2026-14361 security bulletin
CVE: CVE-2026-14361
Behoben in: 0.42.1
photo0
vom Betreiber angegebenes Ziel scheint innerhalb des vorgesehenen Wurzelverzeichnisses zu liegen -> Angreifer platziert vorab ein verlinktes Eltern- oder Endpfad-Element -> writeToFile öffnet den Pfad direkt -> das Dateisystem löst den Schreibvorgang außerhalb des vorgesehenen Verzeichnisses auf -> gerendertes Geheimnis wird umgeleitet -> bereits vorhandenes Ziel kann überschrieben werden
Consul Template rendert Daten aus Quellen wie Consul und Vault.
Der Helper writeToFile ermöglicht es einem Template, ausgewählte Inhalte in eine separate lokale Datei zu schreiben, während ein gewünschter Besitzer, eine Gruppe und ein Berechtigungsmodus angewendet werden.
HashiCorps Dokumentation demonstriert den Helper ausdrücklich mit PKI-Material:
private key -> writeToFile /my/path/to/cert.key
certificate authority -> writeToFile /my/path/to/cert.pem
certificate -> append to /my/path/to/cert.pem
Das macht dies zu mehr als einem gewöhnlichen Ausgabe-Helper.
Die Inhalte, die diese Grenze überschreiten, können umfassen:
Die wichtige Frage war nicht, ob writeToFile einen angeforderten Dateinamen erstellen konnte.
Die eigentliche Frage war:
Schreibt der Prozess an den vom Betreiber vorgesehenen Dateisystemort oder lediglich an das Objekt, auf das der Pfad zum Zeitpunkt des Öffnens aufgelöst wird?
In verwundbaren Versionen vertraute er Letzterem.
Schreib-Helper sind Sicherheitsflächen mit hohem Wert, weil sie von Anwendungsdaten zur Dateisystem-Mutation übergehen.
Die interessanten Fehler sind oft keine klassische ../-Traversal.
Es sind Auflösungsfehler:
Das ist besonders wichtig, wenn der Prozess mit mehr Dateisystemrechten läuft als der Angreifer.
Ein lokaler Angreifer mit niedrigen Rechten kann möglicherweise keine sensible Datei direkt überschreiben.
Aber wenn er eine Pfadkomponente unter einem vorgesehenen Schreibverzeichnis beeinflussen kann, könnte ein privilegierterer Consul-Template-Prozess den Schreibvorgang für ihn ausführen.
Das war die Grenze, auf die ich mich konzentriert habe.
Ich bin dies nicht als generische Path-Traversal-Überprüfung angegangen.
Der bereitgestellte Pfad benötigte keine ..-Segmente.
Er konnte die gesamte Zeit lexikalisch innerhalb des vorgesehenen Wurzelverzeichnisses bleiben.
Die stärkere Frage war:
Werden verlinkte Zielkomponenten abgelehnt, bevor sensible Inhalte geschrieben werden?
Diese Frage ist wichtig für beides:
Der zweite Fall ist besonders nützlich, weil Logs und Konfiguration weiterhin einen harmlos aussehenden Pfad unter dem erwarteten Verzeichnis zeigen.
Das Dateisystem löst ihn jedoch woanders auf.
Die Grundursache war eine direkte, pfadbasierte Dateierstellung ohne link-bewusste Validierung.
In der getesteten Revision wählte writeToFile() einen von zwei Öffnungspfaden.
Der Anhänge-Modus verwendete:
f, err = os.OpenFile(
path,
os.O_APPEND|os.O_WRONLY|os.O_CREATE,
perm,
)
Der normale Schreibmodus verwendete:
dirPath := filepath.Dir(path)
if _, err := os.Stat(dirPath); err != nil {
err := os.MkdirAll(dirPath, os.ModePerm)
if err != nil {
return "", err
}
}
f, err = os.Create(path)
Keiner der beiden Pfade lehnte verlinkte Zielkomponenten ab, bevor die Datei geöffnet wurde.
Das ist wichtig, weil:
os.Create(path) bestehenden Dateisystem-Umleitungen folgt und die aufgelöste Datei kürztos.OpenFile(path, ...) verlinkten Pfadkomponenten im Anhänge-Modus folgtDie gleiche pfadbasierte Annahme setzte sich nach dem Schreiben fort.
Besitzer und Berechtigungen wurden erneut über den Pfad angewendet:
err = os.Chown(path, uid, gid)
err = os.Chmod(path, perm)
Das bedeutete, dass Metadaten-Operationen ebenfalls an einen veränderbaren Pfadnamen gebunden waren, statt an den bereits geöffneten Dateideskriptor.
Weil der Angreifer die Umleitung vorbereiten kann, bevor writeToFile ausgeführt wird.
Für den grundlegenden Angriff ist kein probabilistischer Wettlauf erforderlich.
Die Abfolge ist unkompliziert:
writeToFile öffnet sie direktDas ist die gesamte Verwundbarkeit.
Es stimmt, dass Betriebssysteme bei pfadbasierten Datei-Öffnungen normalerweise Symlinks folgen.
Das macht dies nicht zu einem sicheren Anwendungsverhalten.
Die Sicherheitsfrage ist nicht:
„Hat sich Go wie dokumentiert verhalten?"
Die eigentliche Frage ist:
Hat ein Helper, der sensible gerenderte Daten schreibt, verifiziert, dass das aufgelöste Ziel mit dem vom Betreiber vorgesehenen Ort übereinstimmt?
In verwundbaren Versionen tat er das nicht.
Diese Unterscheidung ist wichtig, weil Consul Template ausgeführt werden kann:
Das Befolgen einer vom Angreifer positionierten Dateisystem-Umleitung in diesem Kontext erzeugt ein echtes Problem an der Privilegien- und Vertrauensgrenze.
Ich habe einen eigenständigen Reproduktionstest rund um das exakte writeToFile-Verhalten im getesteten Commit erstellt.
Das kontrollierte Setup verwendete:
writeToFile übergeben wurdeDer Reproduktionsablauf war:
Das beobachtete Verhalten war:
writeToFile folgte der UmleitungDamit wurden beide Teile der Behauptung belegt:
Ein Symlink als Endkomponente hätte bereits unsicheres Link-Folgen demonstriert.
Aber eine verlinkte Elternkomponente beweist einen stärkeren operativen Punkt:
Auch das bereits vorhandene Ziel war wichtig.
Ohne es würde der PoC nur unerwartete Dateierstellung zeigen.
Indem mit einer vorhandenen Datei begonnen und ihr endgültiger Hash verifiziert wurde, bewies die Reproduktion das Überschreibverhalten direkt.
Das machte das Ergebnis konkreter als eine reine Quellcode-Behauptung.
Dieses Problem erfordert lokalen Dateisystem-Einfluss.
Ein Angreifer benötigt genügend Zugriff, um einen Symlink, eine Directory Junction oder eine gleichwertige Umleitung in oder unterhalb des vorgesehenen Schreiborts zu erstellen oder zu ändern.
Der Consul-Template-Prozess muss dann durch diesen Pfad schreiben.
Die Auswirkungen hängen stark von den Prozessrechten und dem gerenderten Inhalt ab.
Die praktischen Ergebnisse umfassen:
Dies war kein entfernter, nicht authentifizierter beliebiger Schreibvorgang aus einer Standardinstallation.
Aber es war ein klarer lokaler Vertrauensgrenzen-Fehler mit bedeutenden Auswirkungen in privilegierten oder gemeinsamen Dateisystem-Bereitstellungen.
HashiCorp klassifizierte das Problem als:
CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:N/A:N
Der veröffentlichte Basis-Score ist:
4.7 / Medium
Dieser Vektor spiegelt wider:
Die offiziellen Bulletins dokumentieren außerdem ausdrücklich, dass der umgeleitete Schreibvorgang eine bereits vorhandene Datei überschreiben kann.
Der Score ist moderat, weil die Ausnutzung von lokalen Pfadkontrollbedingungen abhängt, nicht weil der Dateisystem-Effekt theoretisch wäre.
Das HashiCorp-Bulletin listet:
Affected: consul-template up to and including 0.42.0
Fixed: consul-template 0.42.1
Der Fix wurde in der Version 0.42.1 am 8. Juli 2026 veröffentlicht.
Der Patch 0.42.1 härte den Schreibpfad auf mehreren Ebenen.
Der gepatchte Helper verwendet os.Lstat(), um zu prüfen:
und lehnt diese Komponenten ab, wenn es sich um Links handelt.
Das schließt die direkten Fälle von Elternverzeichnis-Umleitung und Enddatei-Symlink ab, die vom Bericht und von den Regressionstests abgedeckt werden.
Auf unterstützten Unix-Plattformen wird das Ziel mit O_NOFOLLOW geöffnet.
Dadurch schlägt das Öffnen selbst fehl, wenn die Endkomponente zwischen der Vorprüfung und dem Öffnen zu einem Symlink wird.
Das ist wichtig, weil eine reine Vorprüfung allein ein weiteres TOCTOU-Fenster erzeugen kann.
Die plattformspezifische Implementierung ist unter Windows ein No-op, wo O_NOFOLLOW nicht über denselben Mechanismus verfügbar ist.
Der Patch ersetzte pfadbasierte Besitzer- und Modus-Operationen durch deskriptorbasierte Operationen:
f.Chown(uid, gid)
f.Chmod(perm)
Das bindet Metadatenänderungen an die tatsächlich geöffnete Datei, anstatt den Pfad später erneut aufzulösen.
Der Helper erstellt das Elternverzeichnis nun nur dann, wenn der Stat-Fehler tatsächlich os.IsNotExist ist.
Andere Fehler, wie Berechtigungsfehler, werden zurückgegeben, anstatt in den Schreibpfad fortzufahren.
Der Patch fügte gezielte Tests hinzu für:
Die öffentliche Patch-Diskussion dokumentiert eine wichtige Einschränkung klar.
Die neue Validierung prüft:
Sie durchläuft und lehnt nicht jede höhere Vorfahrenkomponente ab.
Die Maintainer wählten diese Grenze, weil writeToFile kein konfiguriertes Sandbox-Wurzelverzeichnis hat, an dem eine vollständige Containment-Prüfung verankert werden könnte, und gängige Betriebssysteme legitime verwaltete Links in Pfadpräfixen enthalten können, wie /var -> /private/var unter macOS.
O_NOFOLLOW schützt ebenfalls die Endkomponente, nicht jedes Vorfahrenverzeichnis.
Das ändert nichts am Status der gemeldeten Verwundbarkeit oder der offiziellen behobenen Version.
Es verdeutlicht jedoch die genaue Sicherheitseigenschaft, die der Patch liefert:
Diese Unterscheidung ist es wert, in einem technischen Bericht erhalten zu bleiben.
Ich meldete dieses Problem am 21. März 2026 privat an HashiCorp Security als zweiten unabhängigen Consul-Template-Fund.
Der Bericht umfasste:
Die ursprüngliche Folge-E-Mail war nicht in der Berichtswarteschlange des Sicherheitsteams vorhanden, wahrscheinlich weil sie von einem Spam-Filter der Mailingliste abgefangen wurde.
Nachdem ich den vollständigen Bericht erneut weitergeleitet hatte, verband sich HashiCorp mit dem Ingenieurteam und untersuchte ihn getrennt vom ersten Consul-Template-Problem.
HashiCorp behob die Verwundbarkeit in 0.42.1 und veröffentlichte HCSEC-2026-20 am 8. Juli 2026.
IBM veröffentlichte ein entsprechendes Sicherheitsbulletin für dieselbe CVE.
Beide offiziellen Bulletins erkannten den Bericht an als:
Mohamed Abdelaal (0xmrma)
Die wichtigste Lektion ist einfach:
eine Pfadzeichenkette ist nicht dasselbe wie das Dateisystemobjekt, das sie benennt
Diese Unterscheidung ist wichtig, wann immer privilegierter Code angreiferbeeinflusste Pfade schreibt.
Zu prüfen, dass eine Zeichenkette mit einem vorgesehenen Verzeichnis beginnt, reicht nicht aus.
Selbst ein sauberer Pfad ohne Traversal-Sequenzen kann woanders hin aufgelöst werden durch:
Die sensible Operation muss an ein Ziel gebunden sein, dessen Identität an der richtigen Grenze validiert wurde.
Dieses Problem unterstreicht auch eine breitere Regel:
wenn man bereits einen geöffneten Dateideskriptor hat, sollte man sicherheitskritische Operationen über diesen Deskriptor anwenden, anstatt den Pfad erneut aufzulösen
Genau deshalb sind die deskriptorbasierten Chown- und Chmod-Änderungen wichtig.
writeToFile ist für sensibles Material wie Zertifikate und private Schlüssel dokumentiertos.Create oder os.OpenFileChown- und Chmod-Operationen führten zusätzliches Vertrauen in veränderbare Pfade ein0.42.1 fügte Link-Prüfungen, O_NOFOLLOW wo unterstützt, deskriptorbasierte Metadaten-Operationen und Regressionstests hinzuBei dieser Verwundbarkeit ging es nicht um ../-Traversal.
Die Pfadzeichenkette sah korrekt aus.
Das Dateisystemziel war es nicht.
Consul Template akzeptierte den vom Betreiber vorgesehenen Pfad, folgte einer vom Angreifer positionierten Umleitung und schrieb den gerenderten Inhalt in eine andere Datei.
Deshalb wurde dies zu CVE-2026-14361.
Behoben in consul-template 0.42.1.