- Im Jahr 2008 führte die Arbeit an der Behebung eines SSH-Login-Engpasses bei GitHub zur Entdeckung einer anomalen Kollision, bei der verschiedene Nutzer denselben SSH-Key-Fingerprint hatten
- Um das Problem der linearen Suche in der immer weiter wachsenden Datei
authorized_keyszu vermeiden, patchte GitHub OpenSSH so, dass Key-Fingerprints in MySQL nachgeschlagen wurden - Nach dem Rollout des Patches trat ein Problem auf, bei dem per SSH auf Repositories anderer Nutzer zugegriffen werden konnte, doch die wiederholten Kollisionen von Key-Fingerprints ließen sich kaum als bloßer Patch-Bug erklären
- Mit der Veröffentlichung von DSA-1571-1 am 13. Mai 2008 wurde klar, dass Debian OpenSSL rund 18 Monate lang vorhersagbare private Schlüssel erzeugt hatte und die Zahl möglicher Schlüssel pro Nutzer auf etwas mehr als 32.000 reduziert worden war
- Große Sicherheitsvorfälle beginnen oft mit kleinen Signalen nach dem Muster „Das ist seltsam“ — den entscheidenden Unterschied machen die Zeit und Fähigkeit, dieser Spur konsequent nachzugehen
Der Vorfall begann mit einem SSH-Login-Engpass bei GitHub
- Im März 2008 half der Autor, der damals bei Engine Yard arbeitete, GitHub bei einem Problem mit der SSH-Login-Performance; GitHub war Kunde des auf Rails spezialisierten Hosting-Unternehmens
- GitHub bot nach einer SSH-Verbindung zu
git@github.comper Public-Key-Authentifizierung Zugriff auf Git-Repositories - Das Key-Management stützte sich damals auf die übliche Methode über die Datei
~/.ssh/authorized_keys- Wenn SSH eine Anfrage zur Public-Key-Authentifizierung erhält, öffnet es die Datei
authorized_keysund durchsucht sie linear nach einem Eintrag, der zum eingereichten Schlüssel passt - Bei normalen Accounts mit nur wenigen Schlüsseln ist das kein großes Problem, doch bei dem schnell wachsenden GitHub sammelten sich alle SSH-Keys in einer einzigen großen Datei, was die Login-Zeiten spürbar verlangsamte
- Wenn SSH eine Anfrage zur Public-Key-Authentifizierung erhält, öffnet es die Datei
OpenSSH-Patch und Key-Lookups in MySQL
- Nach Prüfung mehrerer Lösungsansätze entschieden sich das GitHub-Team und der Autor dafür, OpenSSH zu patchen, damit Schlüssel anhand ihres Fingerprints in einer MySQL-Datenbank nachgeschlagen werden konnten
- Diese Entscheidung war keine leichtfertige Änderung
- Änderungen an OpenSSH konnten bei Fehlern sicherheitskritische Folgen haben
- Die anderen Optionen waren noch schlechter, daher galt dies als die „am wenigsten schlechte“ Lösung
- Ein erheblicher Teil der Arbeit floss in die Überprüfung, dass die Sicherheit dabei nicht beeinträchtigt wurde
- Nach dem Deployment Anfang April 2008 wurden SSH-Logins schneller, und es sah so aus, als müsse man sich um dieses Problem vorerst keine Sorgen mehr machen
Ein unmöglich wirkendes Symptom: doppelte Key-Fingerprints
- Anfang Mai 2008 erhielt das GitHub-Team Meldungen, dass einige GitHub-Nutzer per SSH auf die Repositories anderer Nutzer zugreifen konnten
- Da das Problem direkt mit der SSH-Key-Authentifizierung zusammenhing und kurz zuvor der OpenSSH-Patch ausgerollt worden war, geriet zunächst der vom Autor geschriebene Code unter Verdacht
- Beim Debugging wurde bestätigt, dass zwei verschiedene Nutzer denselben Key-Fingerprint hatten
- Wenn die Nutzer ihre Schlüssel nicht miteinander geteilt hatten, war so etwas praktisch ausgeschlossen
- Die betroffenen Nutzer kannten einander nicht und gaben an, ihre Schlüssel nie offengelegt zu haben
- Danach wurde bei einem weiteren Nutzerpaar derselbe Befund festgestellt, allerdings mit einem anderen Fingerprint als im ersten Fall
- Damit ließ sich die Situation kaum noch als einzelner Zufall oder als Bug in der Webanwendung erklären
- Nachdem hinreichend klar war, dass der OpenSSH-Patch nicht die Ursache war, nahm die direkte Beteiligung des Autors ab
- Der Autor war kein GitHub-Mitarbeiter und musste sich auch um den Support für andere Engine-Yard-Kunden kümmern
- Das GitHub-Team blieb mit den Nutzern in Kontakt und stellte als Gemeinsamkeit fest, dass die SSH-Keys auf Debian- oder Ubuntu-Systemen erzeugt worden waren
Die Ursache wurde durch die Offenlegung der Debian-OpenSSL-Schwachstelle klar
- Mit der Veröffentlichung von DSA-1571-1 am 13. Mai 2008 wurde die Lage klarer
- Das Debian-OpenSSL-Paket hatte rund 18 Monate lang vorhersagbare private Schlüssel erzeugt
- Die Ursache lag darin, dass ein Debian-Maintainer beim Aufräumen des OpenSSL-Zufallszahlencodes unbeabsichtigt den möglichen Schlüsselraum massiv verkleinert hatte
- Die Zahl möglicher Schlüssel, die ein bestimmter Nutzer erzeugen konnte, schrumpfte von einer „riesigen Anzahl“ auf etwas mehr als 32.000
- Da sich viele Nutzer bei GitHub anmeldeten, dürften einige entsprechend der empfohlenen Praxis eigens neue Schlüssel erzeugt haben, wodurch Kollisionen entstehen konnten
- Diese Veröffentlichung lieferte den entscheidenden Beleg dafür, dass der OpenSSH-Patch des Autors nicht die Ursache war
Spätere Arbeit zu Debian weak keys
- Der Autor kam später noch häufiger mit Debian weak keys in Berührung
- Er betreibt pwnedkeys.com und verwaltet dort ein großes Repository bekannter kompromittierter Schlüssel
- Mit diesen Schlüsseln fand er auch fehlerhaft arbeitende Certificate Authorities
Wie die Zeit, „seltsam“ nachzugehen, den Unterschied machte
- Der Autor konnte nicht herausfinden, wann und wie Luciano Bello die später als CVE-2008-0166 vergebene Schwachstelle genau entdeckt hat
- Da ein stabiles Debian-Release mit dem fehlerhaften Code bereits ein Jahr vor der Offenlegung erschienen war, könnte es Zeit gegeben haben, nach Berichten über Key-Kollisionen tiefer nachzuforschen, weil etwas „seltsam“ wirkte
- Auch die jüngste XZ-Backdoor wurde durch die Beobachtung „Das ist seltsam“ und anschließende intensive Untersuchung aufgedeckt
- Der entscheidende Punkt ist die Fähigkeit und die Zeit, eine solche intensive Untersuchung tatsächlich durchführen zu können
- Der Autor konnte diese tiefergehende Untersuchung damals nicht selbst leisten
- Auch das GitHub-Team war mit Feature-Entwicklung und Incident-Response für einen schnell wachsenden Dienst ausgelastet
- Der Autor bearbeitete seinerseits bei Engine Yard Support-Tickets
- Einen großen Unterschied macht es, wenn zur richtigen Zeit jemand mit den nötigen Fähigkeiten, der Zeit und der Energie eine Spur konsequent bis zum Ende verfolgen kann
1 Kommentare
Meinungen auf Hacker News
Zu der Stelle „Ich konnte nicht herausfinden, wann und wie genau Luciano Bello die Schwachstelle entdeckte, aus der später CVE-2008-0166 wurde“ steht in den damaligen IRC-Logs Folgendes:
17:23 < luciano> has really an accident. I was needing many primes numbers... 0:-)17:23 < Sesse> and you got the same numbers every time?17:25 < luciano> Sesse, not every time :PDie Aussage, dass „die Branche Glück hatte, dass jemand mit den richtigen Fähigkeiten, der nötigen Zeit und Energie genau zum richtigen Zeitpunkt da war“, ist ein Punkt, an dem die Statistik hinter vielen Augen und „Sonnenlicht ist das beste Desinfektionsmittel“ greifbar wird
So unwahrscheinlich es auch erscheinen mag, dass jemand zufällig vorbeikommt und einen Bug entdeckt: Weil es möglich ist, passiert es tatsächlich
Bei proprietärem/geschlossenem Code liegt diese Wahrscheinlichkeit nahe null
Jemand bemerkte etwas Merkwürdiges und konnte anhand des Source Codes zusammen mit der realen Situation erkennen, dass etwas Verdächtiges passiert war
Er kontaktierte Sicherheitsexperten der großen Distributionen und ließ es weiter prüfen; auch sie bestätigten das Sicherheitsproblem und konnten sofort reagieren
Nach der Veröffentlichung konnten Menschen mit Expertise in verschiedenen Bereichen von Software und Sicherheit untersuchen, was wie gemacht worden war und welche Risiken bestanden
Auch verdächtige Commits desselben Entwicklers in anderer Software wurden nachverfolgt und überprüft, und die Analyse ihrer Auswirkungen läuft weiter
Die einzelnen Distributionen wurden sensibler für die Details, wie Kompromittierungen rund um Build-Archive entstehen können, und begannen, Wege zu finden, ähnliche Fälle künftig zu erkennen und zu verhindern
Im Vergleich zu Closed Source wäre ein Bericht wie „die Software ist etwas langsam“ vor einer tatsächlichen Ausnutzung vermutlich kaum beachtet worden
Selbst wenn ein Unternehmen es schließlich herausgefunden hätte, wäre wohl nur eine sehr vorsichtige Erklärung mit minimalen Informationen erschienen, was die Fähigkeit der gesamten Branche, Wiederholungen zu vermeiden, stark beeinträchtigt hätte
Allerdings ist die Wahrscheinlichkeit groß, dass man das Problem nicht beheben kann oder dass gar nichts unternommen wird
Die meisten Menschen wissen nicht, was sie tun sollen, wenn sie einen Bug entdecken. Mir ging es vor sehr langer Zeit genauso, und erst später erkannte ich, dass Dinge, die ich gesehen hatte, Bugs waren
Die Details sind nach fast 30 Jahren verschwommen, aber ich erinnere mich, dass ich unter Windows beim Herumprobieren mit Microsoft NetMeeting einen Crash durch einen Buffer-Overrun-Fehler auslösen konnte
Damals war ich Computeranfänger und verstand nicht, dass ein Buffer Overflow in einer Netzwerkanwendung eine sehr schlechte Sache ist. Vielen, die schon lange in der Branche waren, ging es offenbar ähnlich
Damals war es außerdem viel schwieriger, Sicherheitsprobleme zu melden, und je nach Fall sogar riskant
Am Ende braucht es mehrere Dinge: dass man auf ein Problem stößt, genug tiefes Computing-Verständnis hat, um zu erkennen, dass es schlecht ist, einen Weg hat, den Bug an eine Stelle zu melden, an der Menschen ihn sich ansehen, und eine Sicherheitskultur, die weiß, wann und wie solche Meldungen bearbeitet werden müssen
Beim Lesen desselben Satzes fragte ich mich allerdings, wie viele schwerwiegende Sicherheitsbugs wie Heartbleed, CVE-2008-0166 oder der xz-Vorfall unentdeckt beziehungsweise unveröffentlicht im Umlauf sind
Eine wichtige Tatsache, die ich über diese Schwachstelle erst kürzlich erfahren habe, ist, dass diese Änderung nicht übereilt vorgenommen wurde
Der Maintainer stellte das von ihm beobachtete Problem auf die OpenSSL-Mailingliste, bat um Feedback, schlug einen Fix vor und erhielt auch einige Antworten, unter anderem von Upstream
Das Ergebnis war eine schreckliche Schwachstelle, aber es wirkt eher wie extrem großes Pech, dass alle das Problem übersahen
Außerdem rief der Upstream-Code von OpenSSL undefiniertes Verhalten auf. Deshalb hätte es gültig sein können, wenn der Compiler exakt dieselbe Transformation vorgenommen hätte wie der Debian-Maintainer
Damals fühlte sich das wie eine akademische Diskussion an. Man dachte: Ein Compiler wird doch wohl nicht so gemein sein
Später verstand man besser, dass undefiniertes Verhalten grundsätzlich vermieden werden sollte
Und als acht Jahre später Heartbleed entdeckt wurde, wurde allen plötzlich klar, wie schlecht OpenSSL gewartet worden war
Zur Verteidigung: Es war fast reine Freiwilligenarbeit, und glücklicherweise verbesserte sich die Situation später durch Finanzierung
Bei Code für einen sicherheitskritischen Zufallszahlengenerator scheint ein Test wirklich nötig, der eine enorme Menge an Zufallszahlen erzeugt und anschließend prüft, ob sie alle eindeutig sind
Wenn man so etwas liest, fragt man sich, wie wahrscheinlich es ist, dass so etwas bei der Seed-Erzeugungsfunktion eines der beliebten Bitcoin-Hardware-Wallets bereits passiert ist oder künftig passieren wird
Und auch, wie die Folgen aussehen würden
In den vergangenen 22 Monaten hat sich Unciphered mit einer Schwachstelle in BitcoinJS beschäftigt, das weithin für die Erstellung browserbasierter Kryptowährungs-Wallets verwendet wird, sowie mit den Produkten und Projekten, die mit dieser Software erstellt wurden
Über die Jahre führte diese Schwachstelle dazu, dass eine erhebliche Zahl verwundbarer Kryptowährungs-Wallets erzeugt wurde
Denn bei der SSH-Schwachstelle muss man aktiv prüfen, ob der Server, auf den man zugreifen will, einen der schlechten Fingerprints hat; bei Wallets hingegen könnte man im Netzwerk automatisch auf das Geld anderer Leute zugreifen
Allerdings ist es in diesem Fall eher unwahrscheinlich, dass das absichtlich eingebaut wurde
Mit heutiger Technik wären dafür zwar Millionen Jahre Rechenzeit nötig, aber für einen staatlichen Akteur, der nahezu unbegrenzt Geld einsetzen kann, um diese Rechenleistung in wenigen Wochen aufzubringen, liegt es womöglich nicht außerhalb des Möglichen
Am Ende könnte der Zeitpunkt kommen, an dem jeder, der eine Adresse kennt, auf alle Wallets zugreifen kann
Wenn man zum Ziel von jemandem mit Verstand und Geld werden kann, ist Bitcoin kein besonders sicherer Ort, um Wert aufzubewahren
Der Satz „Ezra Zygmuntowitz brachte mich mit GitHub zusammen und verschaffte mir Zeit mit dem GitHub-Team, um dem Problem auf den Grund zu gehen“ ist lustig
Vielleicht, weil ich kein Muttersprachler bin, aber ich las es auch so, als gebe es ein großes Problem mit dem GitHub-Team selbst, und erwartete, dass die nächsten Sätze dem nachgehen würden
Bei der Stelle „Ich frage mich, wie lange es gedauert hätte, bis es entdeckt worden wäre, wenn Luciano es nicht gefunden hätte“ denke ich, dass wohl nur GitHub oder ein großer Cloud-Anbieter zufällig darauf gestoßen wäre
Denn es gibt nicht viele Orte, an denen Tausende oder Zehntausende von User Keys gespeichert sind
Es geht darum, ob man den Satz als „(dem Problem auf den Grund gehen) (zusammen mit dem GitHub-Team)“ lesen soll oder als „(dem Problem beim GitHub-Team) auf den Grund gehen“
Das korrekt zu behandeln, gilt als ziemlich schwierig
Nach meinem Verständnis wurde der OpenSSL-Zufallszahlengenerator mit nicht initialisiertem Stack-Speicher und der PID geseedet, und Debian sorgte dafür, dass nur noch mit der PID geseedet wurde
Aber war das nicht schon ohne den Debian-Patch ziemlich gefährlich?
Im OpenSSL-Code gab es zwei Stellen, an denen Byte-Blöcke kopiert wurden, und eine davon konnte nicht initialisierte Müllwerte kopieren. Das war tatsächlich falsch
Jemand schrieb einen Patch, um das zu beheben, und später sagte jemand, ganz ohne Hilfe eines LLM und nur aus rein menschlicher Inkompetenz: „In der Nähe gibt es noch eine ähnliche Kopie, die sollten wir auch entfernen“
Debian nahm einen Patch auf, der beide Änderungen enthielt
In der Folge kopierte OpenSSL nun gar keine Bytes mehr
Gut, dass keine nicht initialisierten Daten kopiert wurden, aber echte zufällige Entropie wurde ebenfalls nicht mehr in den Pool kopiert. Ups
Bei der Stelle „Nachdem wir mehrere mögliche Lösungen geprüft hatten, kamen wir zu dem Schluss, dass die am wenigsten schlechte Option darin bestand, OpenSSH so zu patchen, dass es Schlüssel in einer MySQL-Datenbank nachschlägt, die über den Key-Fingerprint indexiert ist“: Warum MySQL und nicht sqlite?
Es ging darum, den Zugriff auf ~/.ssh/authorized_keys schnell zu machen, und genau für solche Fälle ist MySQL eigentlich gemacht
OpenSSH so zu patchen, dass es ~/.ssh/authorized_keys.db prüft, wäre vermutlich weniger Arbeit gewesen, als es für MySQL zu patchen
Gut möglich, dass MySQL ohnehin schon im Betrieb war. Dann hätte es auch keine Anfangskosten gegeben, die Daten dort abzulegen
Schließlich musste die User-Datenbank sowieso schon irgendwo existiert haben
Abgesehen davon, dass ein paar schwache Schlüssel gefunden wurden, ist interessant, dass langsame SSH-Loginzeiten aus mehreren Gründen ein Faden sind, an dem es sich zu ziehen lohnt
Eine weitere interessante Episode ist der Fall, in dem per größtem gemeinsamen Teiler RSA-Schlüssel erkannt wurden, die einen gemeinsamen Faktor
poderqhatten: https://factorable.net/weakkeys12.extended.pdfIch frage mich, ob GitHub immer noch ein gepatchtes openssh betreibt
Man kauft eine Kopie von GitHub Enterprise, entfernt die Datei-Obfuskation und schaut sich um. Das Deobfuskieren ist eine interessante Herausforderung und nicht allzu schwer
Leider ist es nicht Open Source, daher kann man den Code nicht teilen, darüber sprechen oder auf GitHub verlinken
Wenn GitHub Enterprise aber noch so einen Patch verwendet, ist die Wahrscheinlichkeit groß, dass das echte produktive GitHub es ebenfalls tut
~/.ssh/authorized_keyszu packenWenn man per telnet auf Port 22 von
github.comgeht, wird der Versionsstring sofort ausgegebenKorrektur: Anfangs hatte ich golang gesagt, aber bei der Überprüfung stellte sich heraus, dass Bitbucket golang verwendete