xz-Backdoor – eine Aufarbeitung

Die kürzlich aufgedeckte Backdoor in der Open Source-Software xz ließ meinen Kollegen Justus Tartz und mich nicht mehr los. Die Thematik ist komplex und hat Implikationen für die Art, wie wir mit Open Source-Software in Zukunft umgehen sollten. Dieser Artikel stellt das Ergebnis unserer Recherchen und Überlegungen dar.

Angriff auf das Internet

Am 28. März 2024 kam es zu einer Beinahe-Kernschmelze in der weltweiten Open-Source-Infrastruktur. Sie wurde (Ehre, wem Ehre gebührt) von Andres Freund, einem der Entwickler von Postgresql und Principal Software Engineer bei Microsoft, verhindert. Ihm fiel auf, dass seine SSH-Anmeldung an einem Linux-Testsystem eine halbe Sekunde länger dauerte als gewöhnlich. Was war passiert?

Blicken wir zurück ins Jahr 2021. Ende Januar dieses Jahres erschien ein neuer GitHub-Account mit dem Namen Jia Tan auf der Bildfläche, der sich ab Ende 2021 aktiv in die Entwicklung der xz Utils einbrachte. xz ist ein Tool, das verlustfreie Datenkompression ermöglicht und in nahezu allen Unix-ähnlichen und damit auch in allen Linux-Systemen zum Einsatz kommt, beispielsweise um den Bootloader vor dem Systemstart zu entpacken. Der Entwickler von xz, Lasse Collin, zeigte sich erfreut über den Enthusiasmus und die damit einhergehende schnelle Weiterentwicklung von xz, welche aufgrund gesundheitlicher Probleme Collins‘ bis dahin schon länger nur schleichend vorankam. Spätestens ab dem dritten Quartal des Jahres 2022 hatte Jia Tan in diesem Projekt den Status eines Maintainers, ab Anfang 2023 wurden die ersten eigenen Commits gemerged. Dazu später mehr.

Jia Tan brachte in der Zeit zwischen Anfang 2021 und April 2024 rund 700 Änderungen in den xz-Quellcode ein. Doch nicht nur dort war dieser Account aktiv, auch in anderen Open Source Projekten wie libarchive, die mit xz in enger Abhängigkeit stehen, wurden bereits ab 2021 Änderungen eingebracht. libarchive ist eine Bibliothek zum Packen, Entpacken und Verändern von Archiven wie zip und rar, welche unter anderem auch in Microsoft Windows zum Einsatz kommt.

Als am 28.03.2024 die schlechte Performance des OpenSSH-Servers von Andres Freund bemerkt wurde, wusste er noch nicht, welchen Impact seine Entdeckung haben sollte. Er begann, den sshd-Prozess zu debuggen, um herauszufinden, an welcher Stelle es zu den beobachteten Verzögerungen kam. Ihm fiel auf, dass der Prozess selbst bei fehlerhaften Logins eine bemerkenswert hohe CPU-Last erzeugte und tauchte tiefer in die Abhängigkeiten auf seinem System ein. Die Spur führte ihn zu der Bibliothek liblzma, welche als Teil von xz paketiert wird. Er erinnerte sich, dass er bei automatisierten Tests einige Wochen zuvor eine Warnung von Valgrind, eine Werkzeugsammlung für die dynamische Fehleranalyse, gesehen hatte, die ebenfalls auf diese Library zurückging.

Ein Review des Quellcodes für xz brachte daraufhin zu Tage, dass offensichtlich eine Backdoor hinzugefügt wurde, deren Funktion zu diesem Zeitpunkt noch unklar war. Klar war jedoch, welcher Nutzer die entsprechenden Änderungen gemacht hatte: Jia Tan.

Was folgte war ein aufregendes Oster-Wochenende. Zahlreiche Sicherheitsforscher und Enthusiasten stürzten sich auf den Quellcode und arbeiteten in Rekordzeit heraus, wie die Backdoor implementiert wurde, welche Systeme sie gefährdete, wo sie bereits ausgerollt worden war und wie sie bisher verborgen bleiben konnte. Es zeichnet sich ein Krimi ab, der aufgrund der Länge und der Tiefe der Planung nicht zuletzt den Verdacht weckt, dass hier nicht nur eine kleine Gruppe von bösartigen Hackern oder gar eine Einzelperson am Werk war.

Die manipulierte Version von xz-utils wurde durch die schnelle und öffentliche Bekanntmachung seitens Andres Freund und die ebenso schnelle Reaktion der einzelnen betroffenen Distributionen nur auf wenigen Systemen ausgerollt. Betroffen waren für kurze Zeit Debian unstable/testing, darauf aufbauend Kali Linux sowie Fedora Rawhide und Fedora Linux 40 Beta. Auch der eigentliche Maintainer Lasse Collin reagierte schnell auf die Meldungen und half, den Schaden zu begrenzen. Siehe dazu seine Informationsseite.

Timeline eines Großangriffs

Der folgende Abschnitt basiert grob auf https://research.swtch.com/xz-timeline, um die Ereignisse in eine sinnvolle zeitliche Relation zu setzen.

Ende 2021 reicht der Account Jia Tan seinen ersten kleinen Patch bei der xz-devel Mailingliste ein. Es handelt sich um eine Konfigurationsdatei, die auf lange Sicht dazu dienen sollte, die Lesbarkeit des Codes zu verbessern, indem Code-Editor-Programmen Richtlinien mitgegeben werden, wie sie den Quellcode formatieren und anzeigen sollen. Eine harmlose, aber sinnvolle Änderung, die vom Maintainer, Lasse Collin, übernommen wird.

Zwei weitere Patches folgen jeweils einen Monat und ein halbes Jahr später, die beide ebenso harmlos sind; auch im Nachgang betrachtet scheint es hier eher um das Erlangen von Vertrauen gegangen zu sein, nicht um die direkte Vorbereitung einer bösartigen Implementierung.

Drei Tage nach dem inzwischen vierten Patch von Jia Tan erscheint ein neuer Nutzer auf der Bildfläche: Jigar Kumar. Weder dieser Account noch die zugehörige E-Mail-Adresse tauchten, soweit es sich nachvollziehen lässt, vorher irgendwo auf – weder auf Mailinglisten, noch bei Github oder sonstwo im Internet. Dieser Account macht nun auf der Mailingliste Druck und beklagt sich darüber, dass der letzte Patch von Jia Tan noch immer nicht gemerged (unter „mergen“ versteht man das Zusammenführen von Änderungen im Quellcode) sei, und dass die Entwicklungsgeschwindigkeit dieses Projektes viel zu langsam sei. Zu diesem Zeitpunkt hatte Lasse Collins bereits mehrere Patches von Jia Tan gemerged.

Etwa einen Monat später erscheint ein weiterer, bisher nirgendwo in Erscheinung getretener Account in der Mailingliste: Dennis Ens. Dieser stellt die Frage, ob das Projekt überhaupt noch aktiv betreut werde, da der Maintainer (Lasse Collin) oft für lange Zeit keine Patches liefere. Dieser meldet sich daraufhin zurück und deutet an, dass Jia Tan möglicherweise in näherer Zukunft im Projekt eine größere Rolle spielen werde, seine eigenen Ressourcen seien derzeit gebunden.

Wenige Tage darauf tritt wieder Jigar Kumar auf den Plan und beschwert sich, dass weiterhin Patches nicht gemerged seien. Wiederum ein paar Tage darauf macht er im Nachbarthread für die Java-Implementierung von xz Druck und drängt darauf, dass ein neuer Maintainer für das Projekt gefunden werden muss. Er unterstellt, dass Lasse Collin das Interesse an xz verloren habe. Dieser antwortet nur einen Tag später und offenbart, dass er unter Anderem schon länger psychisch erkrankt sei (neben anderen Faktoren, die er offen lässt) und daher keine Möglichkeit habe, zeitnah die offenen Patches zu mergen. Auch hier erwähnt er, dass Jia Tan diesbezüglich in Zukunft möglicherweise mehr Verantwortung übernehmen könnte und erinnert daran, dass xz ein Freizeit-Projekt sei.

Zwei Tage später merged Lasse Collin den ersten Commit (ein Commit ist einfach gesagt eine finale Änderung am Quellcode, oft im Rahmen eines Merge), bei dem Jia Tan erstmals explizit als Autor hinterlegt ist.

In den folgenden zwei Wochen melden sich Jugar Kumar und Dennis Ens wiederholt zu Wort und fordern, schnell einen neuen Maintainer einzusetzen. Jia Tan wird nicht namentlich benannt, steht jedoch als einziger Kandidat im Raum und so ist klar, in welche Richtung die Forderungen zielen. Lasse Collin antwortet, Jia Tan sei faktisch schon Co-Maintainer und entsprechende Änderungen seien bereits auf dem Weg.

Die letzte Wortmeldung der beiden verdächtig frischen Accounts erfolgt weniger als einen Monat nach ihrem ersten Auftreten: Jugar Kumar drängt am 22.06.2022 darauf, dass Jia Tan Maintainer-Rechte bekommt, um selber Commits mergen zu können.

Ab Ende September 2022 scheint Jia Tan endgültig Maintainer-Rechte erlangt zu haben. Der Account postet Release Summaries für die anstehenden xz-Versionen, ist über ein gemeinsames Postfach, auf das beide Maintainer Zugriff haben, erreichbar. In der README des xz-Projekts ist er nun ebenfalls als Maintainer neben Lasse Collin geführt.
Ende 2022 merged der Account Jia Tan schließlich den ersten eigenen Commit, was den Zeitpunkt markiert, an dem der Account nachweislich Commit-Rechte erhalten hat.

Mitte Januar 2023 baut Lasse Collin sein letztes Release 5.4.1 für xz, Mitte März erscheint das erste von Jia Tan selbst gebaute Release 5.4.2. Ebenfalls Mitte März ändert Jia Tan die projektbezogenen Kontaktdaten im Projekt oss-fuzz (ein Tool, das Fuzzing-Techniken nutzt, um Programmierfehler im Quellcode automatisiert zu finden) und setzt seine private Mailadresse als Hauptkontakt für xz ein.

Bis hierhin gab es zwar einige Auffälligkeiten, jedoch keine Hinweise auf eine „feindliche Übernahme“. Das Projekt benötigte in der Tat frischen Wind und das Engagement seitens Jia Tan kam Lasse Collin definitiv nicht ungelegen. Vielleicht klingelten vor allem aus der Aussicht auf eine Nachfolge heraus keine Alarmglocken, vielleicht waren die Auffälligkeiten auch zu unterschwellig – faktisch war bis zu diesem Zeitpunkt (nach aktuellem Erkenntnisstand) noch nichts Auffälliges geschehen, das einen fundierten Verdacht hätte wecken können.

Zwei Tage nach der Änderung der Kontaktdaten bei oss-fuzz betritt ein neuer Account die Bühne: Hans Jansen. Dieser sendet einige Patches an das xz-Projekt, die von Lasse Collin gemerged werden. Auch Hans Jansen ist vorher nirgendwo in Erscheinung getreten, weder in der Entwicklerszene noch irgendwo sonst im Internet. Die Patches implementieren eine neue Abhängigkeit von GNU indirect functions, die es erlauben, die globale Funktionstabelle beim Start des Programms zu verändern, bevor diese schreibgeschützt geladen wird. Ohne Kontext eine Änderung, die harmlos wirkt, denn durch sie kann es durchaus zu Performance-Verbesserungen kommen.

Zwei Wochen darauf reicht Jia Tan im Projekt oss-fuzz einen Commit ein, der die GNU indirect function-Unterstützung in oss-fuzz für die Komponente xz deaktiviert, da es angeblich Inkompatibilitäten mit einem Programmbestandteil von xz gebe. Als Maintainer von xz war diese Änderung nicht auffällig und wurde implementiert. Rückblickend führte das jedoch dazu, dass Auffälligkeiten, die ifunc (kurz für GNU indirect funktion) betrafen, von oss-fuzz für das Projekt xz nicht mehr erkannt werden konnten.

Anfang 2024 verschiebt Jia Tan die bisherige xz-Projektseite auf tukaani.org, die bis dato auf dem privat betriebenen Server von Lasse Collin gehostet wurde, zu GitHub Pages, auf die Zugriff für alle Maintainer bestand. Die URL ändert sich auf xz.tukaani.org, die Änderung war also von Lasse Collin abgesegnet, der diese als Inhaber der Domain veranlassen musste.

Am 22.02.2024 startet die lange vorbereitete Implementierung der Backdoor in xz. Jia Tan lädt manipulierte binäre Test-Files hoch, die auf den ersten Blick harmlos aussehen. Solche Dateien werden für automatisierte Tests verwendet, beispielsweise um zu überprüfen, wie das Programm mit fehlerhaften sowie validen Archiven umgeht.

Einen Tag später baut Jia Tan die Version 5.6.0 von xz und fügt eine manipulierte Datei, build-to-host.m4, im Release-Archiv hinzu. m4-Dateien versorgen üblicherweise das Build-Script mit den korrekten Variablen für die jeweilige Umgebung. In diesem konkreten Fall prüft eine Routine des Scriptes, ob es sich bei dem Zielsystem um Debian (deb) oder RedHat (rpm) handelt und implementiert die händisch gebaute und mit an RC4 angelehnten Algorithmen verborgene Backdoor in den Build-Prozess (dokumentiert ist die Entdeckung beispielsweise hier: https://twitter.com/nugxperience/status/1773906926503591970). Die manipulierte m4-Datei taucht in der xz-Repository nicht auf, was jedoch nicht sonderlich auffällt, da beim Paketieren häufig zusätzliche Dateien erzeugt werden, die dann nur im fertigen Archiv, nicht aber im Quellcode vorliegen.

Am nächsten Tag, dem 24.02.2024, fallen bei xz auf Gentoo, einer Linux-Distribution, die ihre Pakete direkt aus den Sourcecode-Quellen baut und keine Paketierung einsetzt, Fehlermeldungen und Abstürze mit Bezug auf ifunc auf. Der Fehler wird diskutiert, da aber nicht mit den vorgebauten Paketen gearbeitet wird, existiert auch die Backdoor-Implementierung auf den betroffenen Systemen nicht und wird daher nicht entdeckt. Es sieht tatsächlich nach einem Bug in der neuen ifunc-Implementierung aus, die nichts mit der Backdoor zu tun hat.

Ende Februar werden die Backdoor-Versionen 5.6.0-0.1 und 5.6.0-0.2 in Debian unstable übernommen. Zeitgleich wird ein Patch von Jia Tan durch Lasse Collin gemerged, der den Support für Landlock (ein recht junges Security-Modul in Linux) durch einen unauffällig platzierten Fehler im Quellcode bricht. Das Script geht durch diesen Fehler letztendlich davon aus, dass das Zielsystem Landlock nicht unterstützt und deaktiviert die zugehörigen Schutzmechanismen. Entweder übersah Lasse Collin den Fehler oder Jia Tan mergte seinen Commit in dessen Namen, was bei GitHub durchaus möglich ist – nachvollziehen lässt sich das im Nachhinein nicht so einfach.

Einen Tag später schickt der Nutzer Github-User teknoraver (einer der vielen Code-Zulieferer für systemd) einen Pull Request (die Aufforderung an ein git-Projekt, eine bestimmte Änderung zu implementieren) an das systemd-Projekt, der das Linken von liblzma (als Teil des xz-Projekts) in systemd beendet. Die Backdoor setzt aber genau auf diesen Mechanismus; ohne dass liblzma in systemd geladen wird kommt die Backdoor nicht zur Ausführung. Diese Änderungsanfrage führt vermutlich dazu, dass Jia Tan in Zugzwang gerät, um die Backdoor so schnell und so weit wie möglich zu streuen, bevor sie komplett wertlos wird.

Anfang März 2024 fallen bei RedHat-basierenden Linux-Distributionen in Bezug auf xz Valgrind-Fehlermeldungen auf, die in der Funktion _get_cpuid von liblzma ihren Ursprung haben. Unabhängig davon wird der von teknoraver eingereichte Patch zum Entfernen von liblzma aus systemd gemerged.

Noch am selben Tag fügt Debian die mit der Backdoor versehene xz-Version 5.6.0-0.2 zum Debian testing-Branch hinzu.
Ebenfalls am 05.03.2024 committet Jia Tan zwei Bugfixes in das xz-Projekt, die die ifunc-Fehler beheben.

Am 08.03.2024 committet Jia Tan einen vermeintlichen Bugfix für die Valgrind-Thematik, der allerdings wohl eher zur Ablenkung vom eigentlichen Problem dienen soll.

Einen Tag später lädt Jia Tan aktualisierte Testdateien hoch, die nun tatsächlich in Valgrind keinen Fehler mehr auslösen, aber weiterhin die Backdoor beinhalten.
Noch am selben Tag baut Jia Tan die aktualisierte Version 5.6.1 von xz und veröffentlicht diese.

Wir erinnern uns an Hans Jansen: Am 25.03.2024 erscheint er erneut auf der Bildfläche, indem er einen Bugreport bei Debian einstellt, in dem er fordert, dass xz-utils zeitnah auf Version 5.6.1 aktualisiert werden soll. Kurioserweise spricht der Account von „seinem Paket xz„, was den Verdacht nahelegt, dass es sich hinter dem Account um dieselbe Person oder Personengruppe handeln könnte, die auch hinter Jia Tan steckt.

Drei Tage später – am Tag der Entdeckung der Backdoor ­– erstellt auch Jia Tan einen Bugreport, um die Aufnahme von xz 5.6.1-1 in Debian zu beschleunigen. Angesichts der anstehenden systemd-Änderung eine nachvollziehbare Handlung einer Person oder Gruppe, die eine über mehrere Jahre vorbereitete Aktion noch zum Erfolg führen will.

Funktionsweise der Backdoor und Auswirkungen

Vorweg eine kurze Linkliste ohne Anspruch auf Vollständigkeit zu verschiedenen Stellen, an denen Erkenntnisse und Analysen zur xz-Backdoor zentral gesammelt und aufbereitet wurden:

https://github.com/amlweems/xzbot
https://gist.github.com/thesamesam/223949d5a074ebc3dce9ee78baad9e27
https://boehs.org/node/everything-i-know-about-the-xz-backdoor
https://en.wikipedia.org/wiki/XZ_Utils_backdoor

Die Backdoor selbst wurde kurz nach Bekanntwerden ihrer Existenz durch diverse Sicherheitsforscher analysiert (Beispielsweise hier: https://bsky.app/profile/filippo.abyssdomain.expert/post/3kowjkx2njy2b). Schon recht früh wurde klar, dass sie sich auf den OpenSSH-Daemon sshd auswirkte; der genaue Wirkmechanismus war anfangs unklar und so ging man vorerst von einem Aushebeln der Authentisierungsmechanismen (Authentication Bypass) aus, was nach wie vor nicht endgültig vom Tisch sein dürfte, da die genaue Funktionsweise der Backdoor bis heute noch analysiert wird. Es zeigte sich jedoch schnell, dass die Backdoor deutlich tiefer ging. Es handelte es sich nach ersten Erkenntnissen primär um keinen Authentication Bypass. Die Backdoor stellte sich vielmehr als eine clever implementierte Unauthenticated Remote Code Execution (RCE, Codeausführung auf einem entfernten System) dar.

Grob gesagt funktioniert die Backdoor (nach aktuellem Wissensstand) so: Der Angreifer meldet sich via SSH mit seinem Public Key an. OpenSSH prüft neben der Berechtigung für die Anmeldung zusätzlich auch noch den präsentierten Public Key sowie die Zertifikatskette dahinter. Genau hier hakt sich die Backdoor ein, indem der Funktionsaufruf zu RSA_public_decrypt via ifunc auf die eigene Schadroutine umgeleitet wird. Diese extrahiert eine im Public Key (genauer: im CA Signing Key) verborgene Anweisung, prüft, ob diese vom Angreifer signiert ist und führt letztendlich die extrahierte Anweisung auf dem Zielsystem aus. Das Ganze geschieht vor der eigentlichen Anmeldung am System und ist so in den Logs nahezu unsichtbar; man sieht maximal den Anmeldeversuch, der aber nicht erfolgreich ist, darüber hinaus werden keine Log-Meldungen generiert.

Die Backdoor als solche wäre auch im laufenden Betrieb nicht erkennbar gewesen. Hätte es nicht die beobachtete Verzögerung bei der Public Key-Anmeldung gegeben, wäre sie vermutlich so bald nicht aufgefallen. Wer sich mit einem nicht vom Angreifer stammenden Public Key anmeldet, sieht nur das ganz normale Verhalten des sshd-Daemons. Nur mit dem richtigen Key und einer versteckten Payload wird die Backdoor aktiviert. Von außen ließe sie sich auf diese Art nicht erkennen.

Und auch wenn die Backdoor letztendlich über SSH aktiviert wird, ist das OpenSSH-Projekt selber außen vor. Es wurden Distributions-spezifische Abhängigkeiten genutzt, die sich bis zum sshd-Prozess auswirkten, die OpenSSH-Entwickler selber hätten nur wenig tun können, um diesen Angriffsvektor im Vorfeld zu verhindern.

Die Auswirkungen, wäre die Backdoor nicht durch Zufall rechtzeitig erkannt worden, könnten kaum schlimmer sein: Große Teile der im Internet betriebenen Linux-Server wären betroffen gewesen. Der oder die Angreifer hätten mit einem Schlag viele wichtige Dienste lahmlegen oder kompromittieren können. Sicher, nicht jeder Linux-Server basiert auf Debian oder RedHat, aber eben doch die Mehrheit. Laut einer Ende 2023 auf heise.de veröffentlichten Trendstudie dominieren Debian– und RedHat-Derivate die Serverlandschaft, das lässt sich zumindest ansatzweise auf das gesamte Internet extrapolieren. Ein Angreifer mit Kontrolle über diese Masse an Servern hätte eine unglaubliche Macht in den Händen. Auch daher wird häufig der Verdacht geäußert, es könne sich unter Umständen um eine Aktion handeln, die staatlich finanziert oder umgesetzt worden sein könnte. Welcher Staat im Genauen dabei beteiligt sein soll bleibt offen. Der asiatisch anmutende, aber in sich nicht ganz stimmige Accountname Jia Tan, die Commit-Zeiten, die in Mailinglisten sichtbare Zeitzone und der für Zugriffe verwendete VPN-Dienst werfen jedenfalls Zweifel auf. Auch die anderen vermutlich beteiligten Accounts, die auf unterschiedliche Herkunft schließen lassen würden, zeichnen eher das Bild einer geplanten Täuschung und Verschleierung. Die zuweilen aufbrandende Sinophobie im Kontext dieses Vorfalls könnte Teil des Kalküls für den Fall eines Fehlschlags gewesen sein.

A propos Kalkül: bisher ist definitiv noch nicht alles aufgearbeitet und erforscht, was im Rahmen dieses Vorfalls geschehen ist. die nächsten Wochen und Monate werden zeigen, ob der oder die Täter auch an anderer Stelle an der Untergrabung der Open Source-Community gearbeitet haben. One down, many to go, oder war das schon das Ende?

Es ist zudem nicht gänzlich unwahrscheinlich, dass noch weitere Funktionen der bisher entdeckten Backdoor zutage treten und dass vielleicht doch noch eine Umgehung der Anmeldeprozesse für eine direkte Systemanmeldung entdeckt wird. Erst kürzlich wurden einige der bereits verlinkten Artikel über die Backdoor um Informationen ergänzt, sie enthalte einen „kill switch“, also eine Funktion, mit der man die Backdoor mit einem gezielten Befehl permanent deaktivieren könne.

Ursachen und Gegenmaßnahmen

Bei der xz-Backdoor handelt es sich um eine gut abgestimmte und raffinierte Kombination aus technischem Verständnis und lange geplantem Social Engineering. Der oder die Angreifer hinter den Pseudonymen Jia Tan (auch: JiaT75, Jia Cheong Tan), Jigar Kumar, Dennis Ens und Hans Jansen kannten sich offenbar gut mit den Interna von xz sowie den Linux-Build-Prozessen, systemd, Valgrind, os-fuzz, OpenSSH und den Funktionsweisen von ifunc und Landlock aus. Die Wahl des xz-utils Pakets wird mit Sicherheit auch nicht zufällig erfolgt sein, denn dass mittels xz der sshd-Prozess angreifbar ist, wird einiges an Forschung vorausgesetzt haben, insbesondere da die Abhängigkeit nicht über das OpenSSH Projekt besteht, sondern nur durch inoffizielle Patches der OpenSSH-Paketmaintainer der betroffenen Distributionen.

Dass die Änderungen im Quellcode nicht oder nicht ausreichend aufgefallen sind, liegt mit Sicherheit zu großen Teilen an der kleinen Menge an Entwicklern, die sich den Code der xz-utils überhaupt anschauen beziehungsweise diesen verstehen. Das Einsetzen des „Wolfs im Schafspelz“ als Maintainer tut sein Übriges. Wer kaum befürchten muss, dass seine zugegebenermaßen auch gut verborgene Backdoor durch Dritte entdeckt wird und sie selber direkt in die Builds integrieren kann, hat nahezu freie Hand. Dass ein kleines privates Projekt die Grundlage für weltweit verwendete Infrastruktur darstellt, ist tatsächlich gar nicht so selten und wurde sogar bereits vor einigen Jahren sehr anschaulich von XKCD aufgegriffen. Es könnte gerade nicht besser passen. Aktuell werden jedenfalls ziemlich viele Maintainer ihre Hobby-Projekte, die so wichtige Zahnräder im Großen und Ganzen sind, noch einmal ganz genau in Augenschein nehmen.

Einer der wichtigsten Punkte ist hier allerdings das erfolgreiche und offenbar über Jahre geplante Social Engineering. Ein überlasteter Entwickler, kaum Bewegung im Projekt, da fällt es leicht, sich in eine Position zu manövrieren, in der man durch geschicktes Ausnutzen der Notlage Vertrauen gewinnt. Der punktuell von vermeintlich unbeteiligten Accounts aufgebaute Druck auf den Maintainer war jedenfalls Kalkül, um den einzuschleusenden Account schnell in eine Maintainer-Position zu bringen.

Bestimmte Änderungen im Code, wie das Entfernen von Sicherheitsmaßnahmen oder das Verwenden unsicherer Funktionen, könnte man noch automatisch im Build-Prozess verhindern, doch an irgendeiner Stelle greifen auch diese Mechanismen nicht mehr. Insbesondere in diesem Fall hätten Automatismen wenig Erfolg, da diese ebenso unter Kontrolle der Maintainer und somit auch den Angreifern stehen. Spätestens bei verschleiertem Code, bei Fremd-Abhängigkeiten oder bei Sicherheitslücken, die den Prüfmechanismen noch nicht bekannt sind, kommen Automatismen an ihre Grenzen und es müsste ein Mensch den Code beziehungsweise die Änderungen bewerten.

Das hätte geschehen können, doch zum Einen war der einzige Mensch, der im aktuellen Fall dazu in der Lage gewesen wäre, aus gesundheitlichen Gründen weniger involviert und zum Anderen gehen kleine Fehler im Review-Prozess häufig unter. Oder hätten Sie den Punkt auf Zeile 15 (zwischen den includes und der Funktion my_sandbox) in den folgenden Änderungen auf Anhieb gefunden?

diff
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -901,10 +901,29 @@ endif()
 # Sandboxing: Landlock
 if(NOT SANDBOX_FOUND AND ENABLE_SANDBOX MATCHES "^ON$|^landlock$")
-    check_include_file(linux/landlock.h HAVE_LINUX_LANDLOCK_H)
+    # A compile check is done here because some systems have
+    # linux/landlock.h, but do not have the syscalls defined
+    # in order to actually use Linux Landlock.
+    check_c_source_compiles("
+        #include <linux/landlock.h>
+        #include <sys/syscall.h>
+        #include <sys/prctl.h>
+.
+        void my_sandbox(void)
+        {
+            (void)prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+            (void)SYS_landlock_create_ruleset;
+            (void)SYS_landlock_restrict_self;
+            (void)LANDLOCK_CREATE_RULESET_VERSION;
+            return;
+        }
+
+        int main(void) { return 0; }
+        "
+    HAVE_LINUX_LANDLOCK)
-    if(HAVE_LINUX_LANDLOCK_H)
-        set(SANDBOX_COMPILE_DEFINITION "HAVE_LINUX_LANDLOCK_H")
+    if(HAVE_LINUX_LANDLOCK)
+        set(SANDBOX_COMPILE_DEFINITION "HAVE_LINUX_LANDLOCK")
         set(SANDBOX_FOUND ON)
         # Of our three sandbox methods, only Landlock is incompatible

Ein weiteres Problem bei git-Repositories ist, dass die gewählten Namen und E-Mail Adressen frei wählbar sind. Das bedeutet, dass die Möglichkeit besteht, dass Jia Tan Commits unter dem Namen des eigentlichen Maintainers Lasse Collin hätte verfassen können. So ist es im Nachhinein kompliziert aufzudröseln, welche Änderungen von Jia Tan kommen und welche nicht. Die Lösung von git für dieses Problem ist das Commit Signing. In der Praxis überprüfen das jedoch nur wenige Menschen die Signaturen und nur ein Bruchteil der Entwickler nutzt diese Funktion. So fällt ein unsignierter Commit nicht auf und es schützt auch nicht vor Änderungen, die nicht unter fremder Identität stattgefunden haben. Signierte Commits können jedoch nach einer bekannten Kompromittierung eines Projektes zu verstehen helfen, welche Änderungen legitim und welche bösartig waren.

Dass derart wichtige Projekte, die die Grundlage für nahezu alle unixoiden Betriebssysteme darstellen, nicht ausreichend öffentlich gefördert werden, ist eine Schande. Eine Schande, die wir alle mitzuverantworten haben. Wir haben uns viel zu lang auf das Open-Source-Prinzip verlassen, glaubten, dass die Möglichkeit, dass jeder mitarbeiten kann, auch bedeutet, dass jeder mitarbeitet. Das Gegenteil ist der Fall. Während bei Großprojekten wie dem Linux-Kernel oder den GUI-Frameworks ausreichend öffentliches Interesse besteht, dass sich dort viele Entwickler beteiligen, greift dieses Prinzip gerade bei den kleinen Kernbibliotheken und Tools nicht, die die Grundlage für die gesamte Infrastruktur darstellen. Oft sind es wie im aktuellen Fall einzelne Entwickler, die ein Programm seit Jahrzehnten im Alleingang entwickeln – meist in der knapp bemessenen Freizeit. Meist getrieben von Anforderungen der darauf aufbauenden Strukturen und damit immer im Zugzwang. Alles unentgeltlich. Selbstverständlich.

Da ist es auch nicht hilfreich, wenn Großkonzerne die Ihre Produkte auf dem Rücken von kleineren Projekten aufbauen, diese nicht nur nicht fördern, sondern gleichzeitig das Einhalten von nie mit den Maintainern vereinbarten SLA-Zeiten einfordern, als handle es sich um eine Lieferantenbeziehung. So ist kürzlich erst Microsoft negativ aufgefallen bei einem Ticket im ffmpeg Projekt, welches unter anderem Verwendung innerhalb von Microsoft Teams findet. Doch was ist die Lösung? Gezielte und geplante Kompromittierungsversuche in FOSS Projekten stellen weniger ein technisches als vielmehr ein soziales Problem dar. Firmen sollten die kleinen Projekte, von denen sie abhängig sind, identifizieren und diese fördern. Finanzielle Unterstützung ist immer gut, aber auch schon Hilfe beim Review von Änderungen und dem Abarbeiten von Tickets kann gerade für kleine Projekte eine große Wirkung haben. Dies kann einem Maintainer eventuell gerade so viel Arbeit abnehmen, dass dieser weniger anfällig für sozialen Druck ist und mehr Energie hat, sich auf andere Aspekte des Projekts zu fokussieren. Mehr Augen auf dem Projekt bilden zudem eine zusätzliche Sicherheitsschicht, die ein Angreifer erst einmal überwinden muss.

„Acropalypse“ NOW!

Aufgrund einer Schwachstelle in der Bildverarbeitungssoftware von Google-Pixel Smartphones (Package-ID „com.google.android.markup“) und dem Windows 11 Snipping-Tool (unter Windows 10 genannt „Ausschneiden und skizzieren“) können aus einem beschnitten Bild („cropped image“) große Teile des Originalbilds wiederhergestellt werden. Sofern durch das Abschneiden des Bildinhaltes sensible Bereiche entfernt wurden, wie z. B. Bankdaten, persönliche Informationen oder Gesichter, ließen sich diese durch fremde Personen auslesen und für bösartige Absichten verwenden.

Hintergrund

Aufgrund einer Schwachstelle in der Bildverarbeitungssoftware von Google-Pixel Smartphones (Google Markup) und dem Windows 11 Snipping-Tool (unter Windows 10 genannt „Ausschneiden und skizzieren“) können aus einem beschnitten Bild („cropped image“) große Teile des Originalbilds wiederhergestellt werden. Sofern durch das Abschneiden des Bildinhaltes sensible Bereiche entfernt wurden, wie z. B. Bankdaten, persönliche Informationen oder Gesichter, ließen sich diese durch fremde Personen auslesen und für bösartige Absichten verwenden.

Simon Aarons und David Buchanan fiel auf, dass dies bei beschnittenen Fotos auf Google Pixel Smartphones nicht der Fall zu sein scheint. Das Smartphone zeigte zwar ausschließlich den beschnittenen Bildbereich an, dennoch blieb die Dateigröße nahezu unverändert. Dies legte den Verdacht nahe, dass die originalen Bildinformationen noch vorhanden sein könnten.

Ihre Analyse ergab, dass beim Speichern des beschnittenen Bildes tatsächlich nicht das alte Bild gelöscht wird Stattdessen wird mit dem neuen, kleineren Bildausschnitt nur der Beginn des alten Bildes überschrieben. Die alten Bildinformationen sind jedoch weiterhin in großen Teilen vorhanden. Aarons und Buchanan entwickelten daraufhin ein Web-Tool mit dem sich das ursprüngliche Bild aus dem einem beschnittenen weitestgehend rekonstruieren lässt. Die Schwachstelle hat trägt die offizielle CVE-ID „CVE-2023-21036“.

Die folgende Abbildung soll den Unterschied zwischen erwartetem Ergebnis und tatsächlichem Ergebnis veranschaulichen. Die „IEND“-Byte-Folge markiert in einer PNG-Datei die Stelle an dem das Ende der Bildinformationen erreicht ist.

Bildbetrachtungsprogramme haben mit dem Anzeigen der Variante (2) des Bildes kein Problem, da die IEND-Byte-Folge korrekt hinter dem beschnittenen Bildausschnitt gesetzt wurde. Aus Sicht der Image-Tools handelte es sich um ein syntaktisch korrekte PNG-Datei. Informationen nach dem IEND werden einfach ignoriert. Mittlerweile wurde eine Sicherheitslücke im Microsoft Snipping-Tool entdeckt, welche sich analog ausnutzen lässt. Wir haben dies zum Anlass genommen weitere Tools auf diese Art von Schwachstelle hinzu untersuchen, jedoch war keines davon anfällig. Die folgenden Tools wurden untersucht:

ToolVersion
IrfanView4.62
Greenshot1.2.10
XnView MP1.4.3
ShareX15.0
Durch die HiSolutions auf „Acropalypse“-Anfälligkeit untersuchte Tools

Zur Untersuchung haben wir die Dateigröße von Originaldatei und zugeschnittener Datei verglichen. Haben beide die gleiche Größe ist der Fehler sehr wahrscheinlich, da eine zugeschnittene Datei mit weniger Bildinhalt entsprechend weniger Speicherplatz benötigen sollte. Bei allen getesteten Tools war die Dateigröße der beschnittenen Datei deutlich kleiner als die der Originaldatei.

Da die Google-Pixel App und und das Microsoft Snipping-Tool eine unterschiedliche Code-Basis verwenden, gehen wir davon aus, dass es sich um einen vergleichbaren Logikfehler bei der Programmierung handelt: Beide Tools schreiben den kleineren Inhalt in die größere Originaldatei ohne die Restlänge der Datei verwerfen. Hinweis auf eine Schwachstelle, welche durch eine anfällige, gemeinsam genutzte Bibliothek entstanden ist, können wir nicht erkennen.

Proof-of-Concept

Das folgende Beispiel zeigt, wie aus einem, auf einem Google Pixel beschnittenes Bild, das Originalbild wiederhergestellt wird (pixel_cropped.png, pixel_original.png). Für die Wiederherstellung wurde dieses Script verwendet.

Das folgende Beispiel zeigt, wie aus einem, mit dem Windows Snipping-Tool beschnittenem Bild, das Originalbild wiederhergestellt wird (windows_cropped.png, windows_original.png).

Da das Snipping-Tool RGBA statt RGB als PNG Image Type verwendet, muss der oben verlinkte Code leicht angepasst werden, um auch hier das Original wiederherzustellen. Die Änderungen betreffenen die folgenden Zeilen:

132c132
< ihdr += (2).to_bytes(1, "big") # true colour
---
> ihdr += (6).to_bytes(1, "big") # true colour with alpha
140c140
< reconstructed_idat = bytearray((b"\x00" + b"\xff\x00\xff" * orig_width) * orig_height)
---
> reconstructed_idat = bytearray((b"\x00" + b"\xff\x00\xff\xff" * orig_width) * orig_height)
149c149
< for i in range(0, len(reconstructed_idat), orig_width*3+1):
---
> for i in range(0, len(reconstructed_idat), orig_width*4+1):

Voraussetzung zur Ausnutzung

Nach Kenntnisstand vom 22.03.2023 müssen die folgenden Voraussetzungen gegeben sein, um eine anfällige Bild-Datei zu erhalten.

  • Das Bild muss mit einer anfälligen Software bearbeitet worden sein.
  • Nach aktuellem Kenntnisstand ist ausschließlich die nachträgliche Wiederherstellung aus PNG-Bildern möglich.
  • Die beschnittene Bilddatei, darf nicht nachträglich komprimiert worden sein, da sonst die verborgenen Bildinformationen entfernt werden.  Dies geschieht jedoch beim Upload auf online-Plattformen häufig automatisch.
  • Für die Rekonstruktion muss die Bildgröße des unbeschnittenen Originalbildes bekannt sein. Diese kann jedoch durch geschicktes ausprobieren von Standard-Displayauflösungen erraten, z. B. Full HD (1920 × 1080 Pixel), oder durch zusätzliche Metainformationen wie beispielsweise dem Handymodell ermittelt werden.

Auswirkungen

Personen mit Zugriff auf mit einer anfälligen Software beschnittene Bilder können große Teile des Originalbildes wiederherstellen. Sofern durch das Abschneiden des Bildinhaltes sensible Bereiche entfernt wurden, wie z. B. Bankdaten, persönliche Informationen oder Gesichter, ließen sich diese möglicherweise wieder sichtbar machen und für bösartige Absichten verwenden.

Der Grund dafür dass manche Bildinformationen verloren gehen, ist dem Aufbau des PNG-Dateiformats geschuldet. Bildinhalte werden in einer Sequenz sogenannter IDAT-Chunks gespeichert. Beim Speichern des beschnittenen Bildes über den Datei-Anfang des Originals werden bestimmte Teile des Originalbildes überschrieben. IDAT-Chunks die auf diese Weise verändert bzw. beschädigt werden können nicht korrekt wiederhergestellt werden, was zu einer wirren oder leeren Pixelfläche im wiederhergestellten Bild führt.

Gegenmaßnahmen

Wurden sensible Bilder mit einem der genannten Tools beschnitten und veröffentlich, dann sollten diese nach Möglichkeit von der betroffenen Plattform gelöscht werden. Dies ist jedoch nur notwendig, wenn die Bilder auf der Plattform unkomprimiert veröffentlicht sind (siehe „Voraussetzung zur Ausnutzung“).

Betroffene Bilddateien können repariert werden, indem das Bild in einem anderen Format (z. B. JPEG) gespeichert wird. Hierdurch werden die verborgenen Dateiinhalte abgeschnitten.

Google hat bereits reagiert und ein Update für seine Pixel-Smartphones veröffentlicht. Dieses sollte umgehend eingespielt werden. Bei der Verwendung des Microsoft Snipping-Tools sollten beschnittene Bilder als neue Datei unter einem anderen Dateinamen gespeichert werden. Dadurch wird verhindert, dass lediglich das alte Bild unsauber überschrieben wird. Ein Patch wurde zum aktuellen Zeitpunkt noch nicht veröffentlicht.