Authentifizierung und Autorisierung
Das Thema Authentifizierung (AuthN) und Autorisierung (AuthZ) ist von enormer Bedeutung, da Schwachstellen in diesen Bereichen überaus häufig auftreten. Da sie so regelmäßig vorkommen, herrscht oft Unsicherheit darüber, was genau sie bedeuten oder was ihre Ursachen sind.
Zur Erinnerung: Die Begriffe decken Folgendes ab:
- Authentifizierung: Wer ist der Benutzer?
- Autorisierung: Worauf sollte der Benutzer Zugriff haben?
Wir betrachten beide Punkte im Folgenden getrennt.
Authentifizierung (Identifizierungs- und Authentifizierungsfehler)
Eine fehlerhafte Authentifizierung kann eine Vielzahl von Schwachstellen umfassen, wie zum Beispiel:
- Fehlende Authentifizierung auf einer bestimmten Seite oder einem Endpunkt
- Mangelnder Schutz gegen Brute-Force-Angriffe (Credential Stuffing)
- Unsichere Prozesse zur Kontowiederherstellung oder Passwortzurücksetzung
- Unsichere Generierung, Validierung, Ablaufsteuerung, Übertragung oder Speicherung von Authentifizierungs-Tokens
- Fehlerhafte oder fehlende Überprüfung, ob sich der Benutzer mit 2FA authentifiziert hat (sofern zutreffend)
Der erste Punkt auf der Liste (fehlende Authentifizierung) ist das mit Abstand häufigste Problem in der Praxis. Oft müssen Entwickler explizit angeben oder konfigurieren, welche Authentifizierungsstufe für eine Seite oder einen Endpunkt erforderlich ist – ein Schritt, der leicht übersehen werden kann.
Es ist bewährte Praxis, sicherzustellen, dass ein System geschlossen ausfällt, anstatt offen. Anstatt jeden Endpunkt einzeln mit der Information zu versehen, dass eine authentifizierte Benutzersitzung erforderlich ist, sollte standardmäßig gelten, dass alle Routen eine authentifizierte Sitzung erfordern, sofern dies nicht explizit anders konfiguriert wurde. Dies kann die Fehleranfälligkeit drastisch reduzieren.
Autorisierung (fehlerhafte Zugriffskontrolle)
Autorisierungsprobleme treten häufig in verschiedenen Formen auf:
- Insecure Direct Object References (IDOR)
- Fehlende Zugriffskontrolle auf Funktionsebene (fehlende AuthZ)
- Privilegieneskalation (horizontal oder vertikal)
Unsichere direkte Objektverweise (IDOR)
Objekte verfügen in der Regel über eindeutige Identifikatoren (IDs), die als Referenzschlüssel dienen. Wenn ein Benutzer eine Anfrage stellt, um eine Bestellung, ein Konto oder Ähnliches einzusehen, enthält diese meist die entsprechende ID. Eine „unsichere direkte Objektverknüpfung“ liegt vor, wenn die Anwendung nicht überprüft, ob der Benutzer (oder ein nicht authentifizierter Nutzer) Zugriff auf dieses spezifische Objekt haben sollte.
Fehlende Zugriffskontrolle auf Funktionsebene
Eine weitere sehr häufige Schwachstelle ist das Fehlen von Autorisierungsprüfungen für eine Seite oder einen Endpunkt (im Gegensatz zu einem Objekt).
Je nach verwendetem Framework müssen Entwickler die Autorisierung entweder im Handler prüfen oder den Endpunkt mit Anmerkungen versehen, um die Anforderungen für den Aufruf festzulegen.
Leider werden diese zusätzlichen Schritte oft vergessen, was häufig erklärt, wie es zu bestimmten Autorisierungsschwachstellen kommt.
Empfehlungen
Standardmäßig geschlossen statt offen
Sowohl bei der Authentifizierung als auch bei der Autorisierung ist das Prinzip, standardmäßig geschlossene statt offene Systeme zu verwenden, von großer Bedeutung.
Je nach Sprache oder Framework ist es bewährte Praxis, sicherzustellen, dass für alle Routen in Ihre Anwendung standardmäßig eine authentifizierte Sitzung mit den höchstmöglichen Rollen oder Berechtigungen erforderlich ist. Dies zwingt Entwickler dazu, die Anforderungen für die jeweilige Route explizit zu überschreiben.
cs
// Sicherstellen, dass Anfragen standardmäßig authentifiziert werden und Admin-Rechte geprüft werden
[Authenticate]
[Authorize("Admin")]
public class SecureController : Controller
{
}
public class MyController : SecureController
{
// Überschreibt das geerbte Authorize-Attribut, um jedem Benutzer Zugriff auf die Seite zu gewähren
[Authorize("User")]
public Page ShowUserProfile() {
}
// Kann nur von einem Admin-Benutzer aufgerufen werden
public Page ShowAdminPage() {
}
// Überschreibt das Authenticate- und Authorize-Attribut, um MIR Zugriff zu gewähren
[AllowAnonymous]
public Page ShowLoginPage() {
}
}
Autorisierungsprüfungen in Diensten erzwingen
Beim Datenzugriff ist es äußerst wichtig, sicherzustellen, dass alle Zugriffe relevante Zugriffs- und Autorisierungsprüfungen einheitlich durchsetzen. Dies wird im Allgemeinen durch die Verwendung von Domänendiensten erreicht.
Weitere Beispiele
Nachfolgend finden Sie eine kurze Sammlung von Beispielen, die den Unterschied zwischen sicherer und unsicherer Authentifizierung und Autorisierung verdeutlichen.
C# - unsicher
Fehlende Authentifizierung
public class AdminController : Controller
{
// UNSICHER: Prüft nicht, ob der Benutzer angemeldet ist, bevor eine Admin-Seite angezeigt wird
public Page ShowAdminPage() {
}
}
Fehlende Autorisierung
[Authenticate]
public class AdminController : Controller
{
// UNSICHER: Prüft nicht die Autorisierung des Benutzers, bevor eine Admin-Seite angezeigt wird public Page ShowAdminPage() {
}
}
C# - sicher
[Authenticate]
[Authorize("Admin")]
public class AdminController : Controller
{
// SICHER: Prüft sowohl, ob der Benutzer angemeldet ist, als auch, ob er die Admin-Rolle besitzt
public Page ShowAdminPage() {
}
}
Sichere Programmierung in der Praxis
Entdecken Sie Richtlinien für sicheres Programmieren, um Schwachstellen wie die OWASP Top 10 zu verstehen und zu beheben, und tauchen Sie in geführte Trainingsmissionen ein, um diese in realistischen Anwendungssimulationen zu üben.