2 Punkte von GN⁺ 2024-04-10 | 1 Kommentare | Auf WhatsApp teilen
  • 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_keys zu 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.com per 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_keys und 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

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

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

 
GN⁺ 2024-04-10
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 :P

    • Wenn man nur dieses Log betrachtet, scheint Luciano beim massenhaften Erzeugen von Schlüsseln stutzig geworden zu sein, weil es mehr Kollisionen gab als erwartet
  • Die 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

    • Den xz-Vorfall sehe ich als großen Sieg für Open-Source-Software
      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
    • Auch in Closed Source werden ständig Bugs gefunden. Viele lassen sich auch ohne Code finden
      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
    • Auch bei proprietärem/geschlossenem Code entdecken Menschen ständig Software-Bugs
    • Dass Open Source besser ist als Closed Source, ist unstrittig
      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

    • Damals hatte ich den Eindruck, dass Debian wegen dieses Bugs ziemlich viel Kritik abbekam, aber wie oben gesagt gab es Versuche zur Zusammenarbeit
      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
    • Statt Pech war es vielleicht eher ein Mangel an Abdeckung durch automatisierte Tests
      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

    • https://www.unciphered.com/blog/randstorm-you-cant-patch-a-h...
      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
    • So ein Problem würde wohl ziemlich schnell entdeckt werden
      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
    • https://news.ycombinator.com/item?id=6195493
    • Der Wintermute-Hack über 160 Millionen US-Dollar wurde durch unsichere Schlüsselerzeugung in einer öffentlichen Library verursacht
      Allerdings ist es in diesem Fall eher unwahrscheinlich, dass das absichtlich eingebaut wurde
    • Wenn man bedenkt, dass jeder Schlüssel deterministisch aus einem Seed Key erzeugt werden kann und dass der Seed Key nicht unendlich ist, ist es letztlich nur eine Frage der Zeit
      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

    • In der Syntax nennt man so etwas ein Problem der Präpositionalphrasen-Anbindung
      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
    • Es lässt sich zwar in beide Richtungen lesen, aber wenn nach „problem“ ein Komma gestanden hätte, wäre die Mehrdeutigkeit verschwunden
  • 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?

    • Dieses Missverständnis scheint ziemlich weit verbreitet zu sein. Tatsächlich lief es aber nicht so ab
      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
    • Das ist falsch. OpenSSL seedete den Zufallszahlengenerator auch mit Daten, die aus /dev/urandom gelesen wurden
  • 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

    • Es waren wahrscheinlich viele Maschinen beteiligt, und normalerweise ist es einfacher, eine einzige Datenbank zu betreiben als mehrere Datenbanken
      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 p oder q hatten: https://factorable.net/weakkeys12.extended.pdf

  • Ich frage mich, ob GitHub immer noch ein gepatchtes openssh betreibt

    • Wenn man möchte, ist es nicht schwer, etwas zu sehen, das dem GitHub-Quellcode ziemlich nahekommt
      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
    • Zumindest werden sie wohl nicht dazu zurückgekehrt sein, alle Schlüssel wieder in ~/.ssh/authorized_keys zu packen
    • GitHub verwendet etwas namens babeld
      Wenn man per telnet auf Port 22 von github.com geht, wird der Versionsstring sofort ausgegeben
    • 2015 verwendeten sie libssh
      Korrektur: Anfangs hatte ich golang gesagt, aber bei der Überprüfung stellte sich heraus, dass Bitbucket golang verwendete
    • Seit OpenSSH 6.2 aus dem Jahr 2013 gibt es AuthorizedKeysCommand, daher ist kein Patch nötig