Schon ein Fehler reicht, und an sich sichere Konzepte greifen ins Leere. Open SSH ist dafür ein Musterbeispiel. Hier hebelt ein Versehen bei der PAM-Integration die ganze Sandbox aus.
Seit Version 5.9verwendet Open SSH zwei Prozesse, um die Interaktion mit Benutzern abzuwickeln: einen nicht privilegierten Childprozess und einen privilegierten Monitorprozess. Dieses Konzept der Aufgabenteilung ist unter dem Namen Privilege Separation bekannt und soll der Sicherheit dienen. Allerdings ist es im vorliegenden Fall nicht so sicher, wie es scheint.
Der Childprozess erledigt die meiste Arbeit. Insbesondere kümmert er sich um das Verarbeiten von Netzwerkdaten. Der Monitorprozess führt dagegen alle Operationen aus, die höhere Rechte benötigen. Etwaige Programmierfehler im komplexen Child-Programmcode sollen nicht zu sicherheitskritischen Problemen bei der Authentifizierung führen.
Die beiden Prozesse kommunizieren mit Hilfe von Sockets, wobei es verschiedene Anfrage- und Antworttypen gibt. Dabei kommen bestimmte Flags zum Einsatz, die genau regeln, wann und wie Anfragen an den Monitorprozess verarbeitet werden. Zudem sind bestimmte Monitoranfragen auch nicht zu jeder Zeit im Ablauf des SSH-Protokolls erlaubt. Sollte eine Anfrage im aktuellen Stadium des Protokolls verboten sein, so ruft der Monitorprozess die »fatal()« -Funktion auf und terminiert.
Es handelt sich um eine Art Sandbox-Prinzip. Wie sich nun herausstellte, hat dieser Ansatz in der aktuellen Open-SSH-Implementierung allerdings dann eine Schwachstelle [1], wenn zusätzlich der PAM-Mechanismus (Pluggable Authentication Modules) aktiviert ist.
Unter anderem trägt der Monitorprozess den Benutzernamen und die Passwd-Struktur in den aktuellen Authentication-Kontext (»struct Authctxt *authctxt« ) ein. Anschließend beginnt die eigentliche PAM-Authentifizierung, indem der Childprozess die »MONITOR_REQ_PAM_START« -Anfrage an den Monitor sendet, um via »pam_start()« eine neue Authentication-Transaktion für diesen Benutzer zu starten. Dabei sendet der Childprozess die »MONITOR_REQ_PAM_INIT_CTX« -Anfrage und nutzt folgende Funktion:
int
mm_answer_pam_init_ctx(int sock, Buffer *m)
{
debug3("%s", __func__)
authctxt->user=buffer_get_string(m, NULL);
[...]
}
Die zweite Zeile zeigt, dass der Childprozess den Benutzernamen selbst noch einmal sendet, was unnötig ist. Schlimmer noch: Der Childprozess überschreibt den vorherigen Benutzernamen.
Das Problem: Sollte ein Angreifer Kontrolle über den Childprozess haben, so könnte er zunächst eine Authentifizierung mit einem Nutzer anstoßen, dessen Passwort er kennt, und dann den Benutzernamen überschreiben (zum Beispiel mit »root« ). Die gesamte weitere PAM-Authentifizierung verlässt sich lediglich auf den zuletzt abgespeicherten Benutzernamen und nicht mehr auf den Namen in der Passwd-Struktur. Dadurch bricht an dieser Stelle das gesamte Sandbox-System zusammen.
Die Attacke ist nicht einfach durchzuführen, denn der Angreifer muss einen gültigen Account auf dem System haben und auch den Childprozess manipulieren können. Trotzdem zeigt die Lücke, wie gut gemeinte Ansätze auszuhebeln sind. Ein übersehenes Detail reicht, um einen ganzen Mechanismus wirkungslos zu machen.
Beide Schwachstellen haben die SSH-Entwickler in der aktuellen Version 7.0 von Open SSH korrigiert.
Infos
- Schwachstelle: http://seclists.org/fulldisclosure/2015/Aug/54





