Mehr Sicherheit: ImageMagick-Schwachstelle behoben
Am Donnerstag, dem 20. Juni 2019, schlug unser Support-Captain Alarm, als eine Schwachstelle gemeldet wurde, durch die ein Transloadit-Server gerootet werden konnte. Das ist die höchstmögliche Berechtigungsstufe auf einer Maschine und der schlimmste Albtraum eines Sicherheitsingenieurs bzw. eines technischen Startup-Gründers.

In diesem Blogbeitrag legen wir offen, wie der Hack ablief, welche Auswirkungen er hatte, was wir unternommen haben und was wir weiterhin planen, um so etwas künftig zu verhindern.
Hintergrund
Transloadit nutzt viele verschiedene Encoding-Werkzeuge, um Medien zu bearbeiten und zu konvertieren. Für Bilder verwenden wir ImageMagick und sponsern dieses Projekt seit vielen Jahren. Bis heute verdanken wir ImageMagick sehr viel.
Kunden von Transloadit bauen ihr Geschäft auf unserem auf und erwarten, dass dieses Fundament solide ist. Das macht es für uns schwierig, Software zu ändern oder zu aktualisieren, denn dabei ändert sich das Verhalten auf subtile und weniger subtile Weise. Deshalb haben wir bisher neue Stack-Versionen veröffentlicht und deren Nutzung optional gehalten. Kunden können die neuen Stacks nach eigenem Ermessen testen, während die alten Versionen weiterhin den Dienst leisten, den sie erwarten und auf den sie sich verlassen.
Die älteste Version, intern als imagemagick_stack v1.0.0 bekannt, wird von uns seit zehn Jahren unterstützt. Wir wollten sie schon länger als veraltet kennzeichnen, doch das muss behutsam geschehen. Wenn wir einen wesentlichen Baustein aus dem Fundament unserer Kunden ziehen, könnte deren Geschäft ins Wanken geraten. Wie bei jeder Software werden Fehler und Schwachstellen gefunden, die gepatcht werden müssen. ImageMagick bildet da keine Ausnahme. Im Laufe der Jahre wurden einige schwerwiegende Schwachstellen in imagemagick_stack v1.0.0 aufgedeckt. Eine davon ermöglichte es, Systembefehle auszuführen, die in speziell präparierten SVG-Bildern versteckt waren.
Das bringt Transloadit in eine Zwickmühle. Einerseits müssen wir dieses robuste Fundament bieten, das sich nie ändert, andererseits müssen wir anfällige Software aktualisieren, um unsere Kunden nicht in Gefahr zu bringen. Wir sind dieses Dilemma mit einer dritten Option angegangen, bei der wir anfällige Software behutsam als veraltet kennzeichnen. Wir helfen unseren Kunden, sich langsam vom Alten zu lösen, und gewinnen dafür Zeit, indem wir die fehlerhafte Software eindämmen.
Unsere Eindämmung besteht aus:
- Einschränken, worauf unsere Encoding-Maschinen Zugriff haben. In diesem Fall nur auf gehashte temporäre Dateien, S3 und die Entgegennahme von Jobs aus einer Queue.
- Scannen von SVG-Bildern (und ähnlichen), die Systembefehle enthalten, und deren Zurückweisung, bevor ImageMagick sie verarbeitet.
- Ausführen unserer Prozesse als nicht privilegierter Benutzer, der auf keinerlei Secrets zugreifen kann, außer auf jene, die vom root-Benutzer in seinen Prozessspeicher eingeschleust wurden.
Was geschehen ist
Am 20. Juni meldete Jeremy Matos, Senior Security Engineer bei GitLab, dass ein Hacker Root-Zugriff auf einen unserer Server erlangt hatte. GitLab hatte eine HackerOne-Kampagne laufen, in der Hacker eingeladen werden, Schwachstellen aufzudecken, und in der Belohnungen für jeden erfolgreichen Hackversuch geboten werden, der verantwortungsvoll offengelegt wird. GitLab übernahm Gitter.im im Jahr 2017, und Gitter (vergleichbar mit Slack, aber für Open-Source-Projekte) nutzte unsere Dienste bereits seit 2014. Wenn Sie in Gitter ein Bild zusammen mit Ihren Chatnachrichten hochluden, konnten der Upload und die Größenänderung von der Transloadit-Plattform übernommen werden.
Der Sicherheitsforscher Sergey Kashatov nahm an diesem Programm teil und versuchte, Gitter.im von GitLab zu kompromittieren, indem er ein Bild mit einer schädlichen Payload hochlud. Er glaubte, eine Schwachstelle bei GitLab gefunden zu haben, doch ohne dass er es zu diesem Zeitpunkt wusste, wurde das Bild auf unseren Servern verarbeitet und damit stattdessen Transloadit kompromittiert. Jeremy bemerkte das schnell und leitete die Unterhaltung mit Sergey weiter, bis wir Sergey direkt ansprechen und erfahren konnten, wie er Root-Zugriff erlangt hatte.
Wie es geschah: die Analyse der „Grundursache“
Richard I. Cook erklärt in How Complex Systems Fail:
„Die nachträgliche Zuschreibung [des] Unfalls zu einer ‚Grundursache‘ ist grundlegend falsch. Da ein offenkundiges Versagen mehrere Fehler voraussetzt, gibt es keine isolierte ‚Ursache‘ eines Unfalls. Es gibt mehrere Faktoren, die zu Unfällen beitragen.“
Auch wenn es womöglich Abstufungen gibt und es manchmal genügt, die primäre beitragende Anomalie zu benennen, halten wir es in diesem Fall für hilfreich, mehr als eine aufzuzeigen.
Wie bereits erwähnt, waren uns Schwachstellen im ImageMagick-Stack v1.0.0 bekannt, und wir haben den möglichen Schaden eingedämmt durch:
Ausführung unserer Prozesse als nicht privilegierter Benutzer
Diese Absicherung fiel weg, als wir Anfang dieses Jahres einen neuen Prozess-Runner eingeführt haben. Um langsames Auslesen von Metadaten abzumildern, wollten wir die Mehrkernfähigkeiten unserer Encoding-Maschinen besser nutzen und diese Arbeit parallelisieren, indem wir mehrere Instanzen desselben Prozesses starten. Dazu haben wir einen bestehenden Orchestrator eingesetzt, der bereits umfangreich in der Produktion im Einsatz war.
Bei der Migration auf den neuen Supervisor haben wir jedoch versäumt sicherzustellen, dass er seine
Prozesse weiterhin unter dem Benutzer ohne Berechtigungen startet. Stattdessen startete er die
Meta-Scan-Prozesse als Benutzer ubuntu, der die Berechtigung hat, auf mehr
Dateien zuzugreifen und sogar zu root zu werden. Das blieb aus zwei
Gründen unbemerkt: A) Wir hatten in der Produktion keine Überwachung, die sicherstellt, dass unsere
Prozesse weiterhin als eingeschränkter Benutzer laufen, und B) in Entwicklung und Test führen wir
der Einfachheit halber alles unter demselben Benutzer aus, sodass diese Situation für die meisten
Entwicklerinnen und Entwickler wie der Normalfall aussehen würde.
Scannen von SVG-Bildern (und ähnlichen)
Unsere Filterung, die schädliche Payloads zurückweisen soll, prüft alle möglichen Angriffsvektoren, tat dies jedoch nicht rekursiv für Includes. SVG-Dateien können auf andere Dateien verweisen, um diese einzubetten. SVG-Dateien ähneln in diesem Sinne stark HTML-Dateien: eine Sammlung von XML-Tags, die beschreibt, wie Dinge gerendert werden sollen, möglicherweise sogar einschließlich weiterer Bilder. Während andere Hacker sich dafür entschieden, schädliche Payloads direkt zu liefern, entschied sich Sergey, ein gültiges SVG hochzuladen, das auf eine andere Datei mit den schädlichen Systembefehlen verwies. Er tarnte diesen Include und gab ihm die Endung .jpeg, wodurch er unser System zusätzlich glauben ließ, es sei sicher, ihn an ImageMagick weiterzugeben.
Auswirkungen
Sergey hat dieses Problem verantwortungsvoll offengelegt und keine Daten gestohlen oder gelöscht. Es ist natürlich möglich, dass ein anderer Hacker diese Schwachstelle ausgenutzt hat, bevor Sergey davon erfuhr, und dabei Daten gestohlen oder gelöscht hat. Unsere Untersuchung ergab keinerlei Hinweise in diese Richtung, doch vollständig ausschließen lässt es sich nicht.
Hätte ein böswilliger Hacker diesen Exploit genutzt und erfolgreich Root-Zugriff auf eine Encoding-Maschine erlangt, hätte er Folgendes tun können:
- Temporäre Dateien einsehen. Diese Dateien sind entweder die Eingabe oder die Ausgabe von einem Robot und existieren nur kurz auf der Encoding-Maschine. Temporäre Dateien werden jedoch nach UUIDv4 ohne Bindestriche benannt und lassen sich nicht zum ursprünglichen Benutzer oder Kunden zurückverfolgen.
- Auf die S3-Buckets von Transloadit zugreifen
Ein kleiner Lichtblick bei dieser erschreckenden Entdeckung ist, dass wir bereits einige Jahre zuvor eingeschränkt hatten, worauf unsere Encoding-Maschinen Zugriff haben. Selbst mit Root-Zugriff könnten die Maschinen also keinen Zugang zu AWS-Ressourcen (abgesehen von S3), zu unserer Datenbank oder zu den Secrets unserer Kunden erhalten.
Korrigierende Maßnahmen
Selbstverständlich haben wir sofort:
- Unsere Filterung verbessert, um extern referenzierte schädliche Payloads zu berücksichtigen, und
diese seltene Art von Bild auf einem anfälligen Stack nicht mehr zugelassen. Die Assembly endet nun
mit einem Fehler und gibt eine Warnung aus, die Sie auffordert, auf Stack
v2.0.3zu aktualisieren. - Den neuen Supervisor-Prozess entfernt und die Ausführung unseres Prozesses als nicht privilegierter Benutzer wiederhergestellt sowie eine Überwachung in der Produktion ergänzt, damit wir alarmiert werden, falls sich das je wieder ändert.
- Eine C-Bibliothek erstellt, die verhindert, dass ImageMagick eigenständig Netzwerkanfragen stellt.
- Alle unsere Schlüssel rotiert (z. B. für unsere eigenen S3-Buckets) und den IAM-Zugriff für die Encoding-Maschinen weiter eingeschränkt, sodass sie nun nur noch Schreibzugriff auf die wenigen Buckets haben, die sie benötigen (z. B. tmp.transloadit.com). Außerdem haben wir die Schlüsselrotation deutlich vereinfacht, sodass wir sie als allgemeine Vorsichtsmaßnahme im Handumdrehen durchführen können.
- Sergey für seine Arbeit entschädigt, da GitLab verständlicherweise die Richtlinie hat, keine Belohnungen für Schwachstellen auszuzahlen, die auf Systemen aufgedeckt wurden, die GitLab nicht selbst betreibt.
- Alle unsere Maschinen auf das neueste LTS von Ubuntu aktualisiert: bionic, das vier weitere Jahre an Patches sicherstellt und zusätzliche Werkzeuge bietet, um unsere Encoding-Prozesse weiter zu isolieren.
Damit sollten die unmittelbaren Probleme gelöst sein. Wir haben Sergey gebeten zu bestätigen, dass Transloadit nicht mehr angreifbar ist, und er bestätigt dies. Das heißt jedoch nicht, dass wir fertig sind. Auf unserer Liste stehen noch:
- Den nicht privilegierten Benutzer auch in Entwicklung und Test verwenden. Das mag die Entwicklung etwas verlangsamen, doch diese Diskrepanz zwischen Produktion und Entwicklung hat dazu geführt, dass diese Schwachstelle unbemerkt blieb.
- Unsere neuen Betriebssystem-Werkzeuge nutzen, um unsere Encoding-Prozesse weiter zu isolieren und ihnen nur Zugriff auf die temporäre Datei zu geben, an der sie gerade arbeiten.
- Das Deprecation-Verfahren starten, um imagemagick_stack v1.0.0 zu entfernen. Wir werden erfassen,
wer ihn noch nutzt, und Warnungen ausgeben, die daran erinnern, einen neueren Stack zu testen.
Außerdem werden wir Kunden anschreiben und jede Unterstützung anbieten, damit sie reibungslos auf
modernere Stacks umsteigen können. Sobald der letzte Kunde die Nutzung eingestellt hat, entfernen
wir
v1.0.0vollständig. - Eine Allowlist von Umgebungsvariablen für unsere Encoding-Werkzeuge umsetzen. Selbst wenn unsere Encoding-Maschinen nur Schreibzugriff auf unsere S3-Buckets haben, besteht wirklich kein Grund, dass ImageMagick davon weiß.
Empfehlungen
Wir halten eine Rotation von Passwörtern auf Ihrer Seite nicht für erforderlich, da es keinen Zugriff auf Passwörter oder Ähnliches gab. Uns liegen keine Hinweise darauf vor, dass dieser Angriff vor Sergey erfolgreich durchgeführt wurde. Auch wenn wir unbefugten Zugriff auf temporäre Encoding-Dateien als das denkbar schlimmste Szenario betrachten, ist die Lage glücklicherweise nicht nur düster. Diese temporären Dateien sind anonymisiert, oft unvollständig (da sie sich gerade im Download befinden) und werden entfernt, sobald das Encoding stattgefunden hat und der Upload abgeschlossen ist.
Dennoch können wir nicht ausschließen, dass ein Hacker temporäre Dateien erlangt hat, und selbstverständlich könnten die Medien selbst identifizierende Informationen enthalten (beispielsweise ein Foto einer Person mit Namensschild oder ein Straßenschild, das ihren Aufenthalt verrät, und wenn es an Google oder Facebook weitergegeben wird, könnten diese Konzerne feststellen, wer abgebildet ist). Aus diesem Grund empfehlen wir Ihnen, dies Ihren Kunden gegenüber offenzulegen, so wie wir es Ihnen gegenüber offenlegen.
Erfreulicherweise sind infolge dieser Schwachstelle keine Zugangsdaten abgeflossen, doch das ist kein Grund zur Selbstzufriedenheit. Auch wenn wir jeden Tag daran arbeiten, das höchste Sicherheitsniveau zu erreichen, wird 100 % Sicherheit immer ein Mythos bleiben. Daher ist es besser, uns nur Schreibzugriff auf einen einzelnen Bucket oder sogar einen einzelnen Ordner zu geben, statt uns Root-Zugriff auf alles zu gewähren – nur damit wir in diesen einen Bucket oder Ordner schreiben können.
Und falls Sie es noch nicht getan haben, ist es außerdem eine gute Idee, Ihren Robot
/image/resize auf "imagemagick_stack": "v2.0.3" zu aktualisieren.
Fazit
Das hat uns zutiefst beschäftigt. Unsere Kunden um jeden Preis zu schützen, ist für den Fortbestand von Transloadit unerlässlich, und unser Unternehmen bedeutet uns alles. In den vergangenen Wochen haben wir rund um die Uhr daran gearbeitet, Aktualisierungen auszurollen, damit so etwas nie wieder passieren kann. Außerdem arbeiten wir mit Sergey und anderen Schwachstellenforschern wie ihm zusammen, um genau das sicherzustellen. Weitere Aktualisierungen folgen noch, doch wir hielten es bereits jetzt für notwendig, dieses Sicherheitsproblem offenzulegen. Hoffentlich gibt Ihnen das als Kunde genug Zeit, damit auf eine für Ihr Geschäft passende Weise umzugehen.
Es tut mir zutiefst leid, dass Fehler auf unserer Seite dazu geführt haben, dass diese Schwachstelle in der Produktion vorhanden war. Wenn Sie nach dem Lesen Fragen oder Bedenken haben, zögern Sie bitte nicht, sich zu melden – ich bin selbstverständlich mehr als bereit, jede weitere Klarstellung zu geben.
