Fedora 38 und OpenSSH’s CVE-2023-28531

Es läuft nicht immer alles glatt, aber die selbst auferlegte Quarantäne ist abgelaufen, Zeit über CVE-2023-28531 zu berichten.

Fedora 38 und OpenSSH’s CVE-2023-28531

Vor einigen Wochen wurde ein Security Audit vom Server gemacht, naja, was manche Leute so als Audit bezeichnen. In Wahrheit war es wohl nicht mehr als ein Portscan + notieren der präsentierten Versionsnummern, man hat es uns nicht genau gesagt. Jedenfalls fiel dem Scanner auf, daß OpenSSH sich mit 9.0p1 meldet, welches diverse Sicherheitslücken enthalten würde, wären da keine Backportfixe gemacht worden. Nur leider konnten wir nicht nachweisen, daß CVE-2023-28531 gefixt wurde, eine Lücke im ssh-agent von OpenSSH. Die kann man aber nur ausnutzen, wenn auch ein SSH-Agent läuft, der dafür empfänglich ist und man dem einen präparierten Schlüssel unterjubeln kann. Eine Menge Wenns, die alle „negative“ waren, da gar kein ssh-agent im Einsatz ist. Der Patch zu CVE-2023-28531 war beim Maintainerteam von Fedora einfach durchgerutscht.

Da meinten die Auditoren, daß es nicht hinnehmbar wäre, daß es eine Lücke gibt, die man nicht ausnutzen kann, weil die ja trotzdem da wäre. Findet den Fehler 😉

Der Auftraggeber legte dann noch eins drauf mit der Feststellung, daß es nicht hinnehmbar wäre, daß ein Scanprogramm bei Ihrem Webserver Alarm schlägt, selbst wenn keine Lücke drin wäre. Bleibt bei so etwas mal ernst, ist nicht leicht 🙂

Warum nicht jede CVE Lücke auch ein echtes Problem ist

Jetzt müssen wir erst mal verstehen, wer betroffen ist.

Es geht um den SSH-Agenten. Dessen Job ist das Bereitstellen von Schlüsseln zu Zugängen beim Versuch sich per SSH auf einem Server einzuloggen und läuft auf der CLIENTEN-Seite. Also bei EUCH auf dem PC. Der Gnome-KeyRing-Daemon ist z.b. so ein SSH-AGENT.

Wenn jemand ssh username@servername eingibt, sieht ssh den Agenten, fragt den ob der einen passenden Key dafür kennt und wenn der Key für die Benutzung zu diesem Server freigegeben ist, dann bekommt ssh den Key und kann sich damit anmelden, oder zumindest es probieren. Natürlich kann man einen SSH-Agenten auch auf einem Server laufen lassen, macht z.B. Sinn wenn man einen Server als einzigen Zugang ins Netz betreibt und sich dann von dort „intern“ (oder extern)  weiter verbindet. Auf einem Multidomain-Webserver ist das aber kein normales Szenario, deswegen läuft das auf unserem Server auch nicht, wäre auch egal, wie Ihr gleich lesen könnt.

Mit dem Befehl ssh-add fügt man Schlüssel in den Agenten ein. Dabei kann man bestimmte Restriktionen setzen, z.b. bei welchen Servern der Key nur erlaubt ist. Und genau da setzte die Sicherheitslücke an, die hatten einfach vergessen die Zugriffsmaske im Code zu vereinigen. Nicht mal eine ganze Anweisung war nötig um das zu fixen:

– int r, constrained = (life || confirm);
+ int r, constrained = (life || confirm || dest_constraints);

Als Folge davon sagte zwar derjenige, der den Schlüssel hinzufügte, daß z.B. der Zugriff mit dem Key auf 1.2.3.4 nicht erlaubt ist, er war dann aber doch möglich. Mit der Sicherheit des zuverbindenen Servers, hat das nichts zu tun, wenn der den Key sieht und der Key für den Userzugang ok ist, dann darf der Key bzw. der User auch einloggen.

Das bedeutet, selbst wenn ein angreifbarer Agent auf unserem Webserver läuft, und der per SSH eingeloggte Benutzer diesen Agenten erreichen könnte und den fingierten Key hinzugefügt bekommt, kann er sich auf dem Server keine Rechte erschleichen. Das diese Lücke überhaupt ausgenutzt werden kann, bedarf folgendem:

1. Ein System X zu dem ein Angreifer nicht privilegierten Zugriff hat, das sich per SSH irgendwo einloggt.
2. Das der Angreifer einen präparierten Key an den Admin dieses System übermittelt.
3. Das der Admin den Key auf anderen Servern einrichtet.
4. Das der Admin den Key auf dem System X mit Restriktionen hinzufügt.
5. Das der Angreifer bestimmen kann, wo sich System X hin verbinden soll.

Wenn man jetzt mal ein paar Sekunden über die Punkte 1-3 reflektiert, stellt man fest, daß 4 und 5 gar nicht nötig sind, wenn das „Ziel“ des Angreifers direkt erreichbar wäre. Da könnte er den gerade von Admin hinzugfefügten Key direkt benutzen, schließlich hat er den ja schon.  Es macht also nur Sinn, wenn es sich um Zielsysteme handelt, die nicht öffentlich erreichbar sind (oder man von einer bestimmten IP kommen muß).

Schlußfolgerungen

1. Es funktioniert nur, wenn ein Agent läuft.
2. Es ist nur relevant für Zugriffe auf andere Server, nicht dem, auf dem der Agent läuft. (Außer der Admin war so dämlich, den Key auf dem Server auch direkt freizugeben.)
3. Es macht nur in komplexen Remote Szenarien Sinn.

Punkt 1 ist aber das absolute Killerargument, weil ohne den Agenten, gibt es auch keine Lücke.

Da heute eine neue Version von OpenSSH gebaut wurde, weil ich mit dem Maintainer von OpenSSH  Dmitry Belyavskiy von RedHat seit Wochen in Kontakt stand und den Patch geliefert habe, hat sich das Problem erledigt und  Ihr könnt jetzt mal OpenSSH updaten gehen 😀 Ich habe mit Dmitry abgesprochen, daß das Update nach den Automatischen Tests direkt ins Stable kommt. Es müßte jetzt also schon bereit sein für Euch 😉  Auf unserem Cluster haben wir das, von Euch aus betrachtet, schon gestern aktualisiert. Von hier aus nochmal ein dickes Danke an Dmitry! 😀

Was mich ein bisschen stört ist der CVE Score von 9.8. Der ist eigentlich nicht angebracht, weil das valide Angriffszenario eher selten zum Einsatz kommt, denn niemand hindert den Angreifer daran, seinen Key bei einem Loginversuch direkt anzugeben: ssh -i kompromitierter.key user@servername . Den Umweg über den ssh-agent kann man sich dabei sparen.

Update Freitag:

Das mit dem „Update direkt ins stable schieben“ hat Dmitry leider vergeigt, daher:

dnf –enablerepo=updates-testing update openssh

Dann kommt das Update gleich.