Unsere Security Analyst*innen im usd HeroLab decken während ihrer Penetrationstests (Pentests) immer wieder Einfallstore auf, die erhebliche Risiken für die Unternehmenssicherheit darstellen. Dabei begegnen ihnen vermehrt die gleichen Schwachstellen. Unsere Blogserie „Top 3 Schwachstellen“ stellt diese dar und gibt Ihnen Tipps für die Vermeidung – für #moresecurity über alle IT-Assets.
Heute betrachten wir die drei häufigsten sicherheitskritischen Schwachstellen, die unsere Analyst*innen bei Penetrationstests von Single Sign-On (SSO) in den vergangenen Jahren identifizieren konnten.
Warum SSO Pentests?
Immer mehr Unternehmen verwenden Single Sign-On (SSO), um Zugriffe auf ihre Dienste und Applikationen zu verwalten. Hierbei wird der Authentifizierungs- oder Autorisierungsprozess auf eine vertrauenswürdige dritte Partei ausgelagert. In einem typischen Anwendungsfall wird hierdurch ermöglicht, dass Endbenutzer sich bei verschiedenen Diensten mit denselben Zugangsdaten einloggen können. Dies bietet den Vorteil, dass Benutzer sich nicht für jeden Dienst andere Zugangsdaten merken müssen.
Sicherheitslücken in der aufgesetzten Single Sign-On Infrastruktur können gravierende Folgen haben. Im schlimmsten Fall kann ein Angreifer den gesamten Authentifizierungsprozess umgehen, was ein erhebliches Risiko für die Vertraulichkeit und Integrität der von den Anwendungen verarbeiteten Daten darstellt. Reputations- und Imageschäden, sowie Schadensersatzzahlungen, sind mögliche Folgen. Im schlimmsten Fall kann dies ein Unternehmen in den Ruin treiben.
Sicherheitslücken in Single Sign-On-Implementierungen entstehen meist dadurch, dass den Entwicklern ein tiefgreifendes Verständnis der internen Funktionsweisen der verschiedenen SSO-Technologien, wie OAuth, OpenID Connect oder SAML, fehlt. Wenn versucht wird, die komplexen Standards der SSO-Technologien selbst zu entwickeln, sind Sicherheitslücken meist vorprogrammiert. Oft wird deshalb auf verschiedene off-the-shelf-Lösungen zurückgegriffen, welche die Funktionalitäten bereits implementiert haben. In unseren SSO-Pentests haben wir jedoch festgestellt, dass auch solche Lösungen oft Sicherheitslücken enthalten. So werden sie beispielsweise vermehrt in einer unsicheren Konfiguration eingesetzt. Außerdem werden zusätzliche Sicherheitsfeatures häufig missachtet, weil die eingesetzte Lösung auch ohne sie funktioniert.
Durch unsere SSO-Pentests haben wir bereits vielen Kunden dabei geholfen, Sicherheitsprobleme in ihren SSO-Implementierungen zu identifizieren und geeignete Gegenmaßnahmen zu implementieren. Wir haben die Schwachstellen, die wir in den letzten Jahren am häufigsten identifiziert haben, in diesem Artikel zusammengetragen.
Unzureichend validierte Redirect URI
In OAuth und OpenID Connect wird ein Benutzer, welcher sich in einer Anwendung einloggen möchte, über einen Authorization / Authentication (AuthN) Request auf einen Identity Provider bzw. Authorization Server geleitet. Dort wird der tatsächliche Login-Prozess durchgeführt. Der AuthN Request enthält eine Redirect URI, welche bestimmt, auf welchen Endpunkt der Benutzer nach dem Login weitergeleitet werden soll. Ein beispielhafter AuthN Request für einen Identity Provider kann wie folgt aussehen:
https://idp.com/auth/protocol/openid-connect/auth?client_id=hb1L0ayT5mOagt10Ct&redirect_uri=https%3A%2F%2Fexample.com%2Fredirect&response_mode=query&response_type=code&scope=openid
Die Redirect URI ist hierbei auf https://example.com/redirect gesetzt. Nach einem erfolgreichen Login würde der Benutzer auf diesen Endpunkt weitergeleitet werden. Wenn diese URL nicht ausreichend strikt konfiguriert ist, bzw. vom Identity Provider nicht ausreichend überprüft wird, dann ergibt sich hieraus ein ernstzunehmendes Sicherheitsproblem, da sensible OAuth Parameter an diese URL übermittelt werden. Abhängig vom gewählten OAuth Flow wird der Identity Provider nämlich einen OAuth 2.0 code oder einen Access Token erzeugen und an diese URL senden. Im folgenden Beispiel wird die Redirect URI im AuthN-Request auf eine vom Angreifer kontrollierte Domain gesetzt:
https://idp.com/auth/protocol/openid-connect/auth?client_id=hb1L0ayT5mOagt10Ct&redirect_uri=https%3A%2F%2Flshthge0o7ngx81uryuse61mbdh45utj.burp.usd.de%2Fredirect&response_mode=query&response_type=code&scope=openid
Schafft es ein Angreifer einen legitimen Benutzer dazu zu bringen, diesen AuthN-Request aufzurufen, dann werden die sensiblen OAuth-Parameter an den Angreifer übermittelt. In dem gezeigten Beispiel kann in den Logs des vom Angreifer kontrollierten Servers erkannt werden, dass der code Parameter erfolgreich übermittelt wurde.
Gelangt ein Angreifer an den code eines anderen Benutzers, stellt dies ein Sicherheitsproblem dar, weil ein Angreifer versuchen könnte, diesen code gegen eine Access Token beim Identity Provider einzutauschen bzw. sich gegenüber der Anwendung als der andere Benutzer zu authentifizieren. Dies ist dann möglich, wenn keine weiteren Schutzmechanismen verwendet werden, welche einen solchen Authorization Code Injection Angriff verhindern. Ein Beispiel hierfür ist im Abschnitt Fehlender PKCE-Schutzmechanismus bei Public Clients beschrieben.
Sicherheitstipp: Um sich vor diesem Angriff zu schützen, sollte auf dem Identity Provider stets konfiguriert werden, dass eine Weiterleitung nur auf eine feste URI zulässig ist. In jedem Fall sollten Wildcards in der URL vermieden werden.
Fehlender PKCE-Schutzmechanismus bei Public Clients
PKCE (Proof Key for Code Exchange) ist ein Schutzmechanismus für OAuth und OpenID Connect, welcher Authorization Code Injection Angriffe verhindert, indem eine Kopplung zwischen AuthN Request und dem Einlösen von Codes im Token Request hergestellt wird. Ohne PKCE ist es bei einem Public Client jedem möglich, einen code über einen Token Request einzulösen. So können Angreifer ohne weitere Hürde einen gestohlenen code gegen einen Access Token für den kompromittierten Nutzer eintauschen. Dies ist insbesondere deshalb möglich, da bei einem Public Client kein client secret verwendet wird, bzw. dieses öffentlich bekannt ist. Ein Token Request, bei welchem ein code für einen Access Token eingetauscht wird, sieht beispielsweise wie folgt aus:
Wie in dem Request zu erkennen ist, werden keine weiteren geheimen Werte zum Einlösen des Codes benötigt. Gelangt ein Angreifer an einen code eines anderen Benutzers, kann er diesen also einfach selbst einlösen. Der code kann auf verschiedene Weisen entwendet werden, beispielweise durch unzureichende Referrer-Konfigurationen, durch Cross-Site-Scripting-Angriffe oder durch eine unzureichend validierte Redirect URI. Wenn der code von einem administrativen Benutzer gestohlen wurde, dann hat der Angreifer durch den erhaltenen Access Token Zugriff auf alle Ressourcen dieses Admins.
PKCE kann einen solchen Authorization Code Injection Angriff erschweren bzw. verhindern, indem beim Token Request ein zusätzliches Geheimnis, der code_verifier, mitgesendet werden muss. Hierbei handelt es sich um das Ursprungsbild des Gegenstücks code_challenge, welche der SHA256-Hash des code_verifier ist. Der code_verifier selbst wird vom Service Provider initial zufällig erzeugt. Beim AuthN Request wird daraufhin vom Service Provider die code_challenge berechnet und als Parameter mit übertragen. Zusätzlich wird der code_challenge_method Parameter mit dem Wert S256 (für SHA-256) übermittelt. Ein solcher AuthN Request, welcher PKCE verwendet, ist im Folgenden dargestellt:
https://idp.com/auth/protocol/openid-connect/auth?client_id=app&redirect_uri=https%3A%2F%2Fvulnerable-service-provider.com%2Fauth&response_mode=query&response_type=code&scope=openid&code_challenge=6BAUM6cUUJUniEQGssx1Zu-NDFxs7buuZaNIpRaEy8k&code_challenge_method=S256
Eine Anfrage zum Einlösen eines Codes müsste dann wie folgt aussehen, damit sie vom Identity Provider akzeptiert wird:
Der Identity Provider würde den Token Request nur akzeptieren, wenn der SHA256 Hash des code_verifier dercode_challenge entspricht, welche ursprünglich im AuthN Request übertragen wurde. Durch diesen Mechanismus ist ein Angreifer nicht in der Lage, einen gestohlenen code gegen einen Access Token einzutauschen, da ein Angreifer zumeist keine Kenntnisse über den code_verifier hat.
Sicherheitstipp: Wir empfehlen, in OAuth- und OpenID-Connect-Implementierungen den PKCE-Mechanismus zu verwenden. Es existieren bereits viele Libraries und Frameworks, die dies einfach ermöglichen. Auf dem Identity Provider muss dann zudem, abhängig von der jeweiligen Implementierung, konfiguriert werden, dass PKCE verwendet und erzwungen werden soll.
Nicht validierte SAMLResponse
Die Security Assertion Markup Language (SAML) ist ein standardisiertes Single Sign-On Protokoll, welches XML-Signaturen benutzt und für die Authentifizierung von End-Benutzern verwendet werden kann. Ähnlich wie bei OpenID Connect kann ein Service Provider den Login-Prozess auf einen Identity Provider (IdP) auslagern. Nachdem der Benutzer sich beim Identity Provider authentifiziert hat, generiert dieser eine SAMLResponse, welche der Endnutzer anschließend an den Service Provider übermittelt. Diese SAMLResponse enthält alle nötigen Autorisierungsinformationen für den Service Provider. Dazu gehören beispielsweise der Name des Benutzers und andere Attribute wie Gruppenzugehörigkeiten oder Berechtigungen. Um die Integrität und Authentizität der SAMLResponse und der darin enthaltenen Informationen sicherzustellen, wird die SAMLResponse ganz oder teilweise durch den IdP signiert. So kann sich der Service Provider nach korrekter Verifizierung der Signatur(en) sicher sein, dass die dort enthaltenen Nutzerattribute korrekt und vertrauenswürdig sind.
Verifiziert der Service Provider die Signatur(en) allerdings nicht ordnungsgemäß, können Angreifer eigene SAMLResponse erstellen und deren Inhalt ganz oder teilweise kontrollieren. Dies kann es Angreifenden erlauben, sich unberechtigten Zugang zu Anwendungen zu verschaffen oder über Änderung ihrer Attribute deren Rechte auszuweiten.
Dass eine Anwendung die SAMLResponse nicht korrekt validiert, identifizieren wir regelmäßig in unseren Pentests. Ein typisches Angriffsszenario ist es, das Signatur-Element aus der SAML-Response zu entfernen.
Eine vom IdP ausgestellte SAMLResponse kann dekodiert wie folgt aussehen (gekürzt):
Diese SAMLResponse enthält ein <Signature>-Element, welches die zu schützenden Elemente, wie Benutzername oder Berechtigungen, signiert. Da diese Signatur durch den Nutzer eigenständig an den Service Provider gesendet wird, kann sie von einem Angreifer entfernt werden. Zusätzlich können die Berechtigungen des Nutzers über seine Gruppenzugehörigkeit verändert werden. Im folgenden Beispiel wurde diese auf ADMIN gesetzt.
Wenn der Service Provider diese manipulierte SAMLResponse akzeptiert und dadurch den Benutzer authentifiziert und autorisiert, liegt zumeist eine kritische Schwachstelle vor, bei der Angreifende ihre Berechtigungen beliebig ausweiten können.
Sicherheitstipp: Für die Sicherheit ist es essenziell, dass Service Provider die Signatur einer SAMLResponse korrekt prüfen. Nur, wenn die Signatur korrekt ist, darf der Benutzer authentifiziert und autorisiert werden.
Fassen wir noch einmal zusammen
Der Schutz von Single Sign-On-Lösungen ist im Kontext der Cybersicherheit von Unternehmen von zentraler Bedeutung. Fehlkonfigurationen oder Schwachstellen der implementierten Lösung können weitreichende Folgen haben, bis hin zum Verlust der Vertraulichkeit, Integrität und Verfügbarkeit der Anwendungs- und Nutzerdaten. Die Behebung von Schwachstellen wie unzureichend validierter Redirect URI, fehlendem PKCE-Schutzmechanismus bei Public Clients und nicht validierter SAMLResponse ist daher unverzichtbar.
Unsere Single Sign-On Penetrationstests (SSO Pentest) sind speziell darauf ausgerichtet, diese und andere Schwachstellen aufzudecken und zu entschärfen. Sie bieten das nötige Fachwissen und die proaktiven Maßnahmen, um die Sicherheit und Widerstandsfähigkeit gegenüber sich entwickelnden Cyber-Bedrohungen zu verbessern. Kontaktieren Sie uns, wir helfen Ihnen gern.