ISMS

API-Sicherheit: Authentifizierung, Rate Limiting und Input Validation

TL;DR
  • APIs sind die am häufigsten angegriffene Komponente moderner Anwendungen. Die OWASP API Security Top 10 beschreiben die kritischsten Risiken.
  • Authentifizierung (wer bist du?) und Autorisierung (was darfst du?) sind zwei verschiedene Dinge. Beide müssen bei jedem API-Request serverseitig geprüft werden.
  • OAuth 2.0 mit PKCE ist der aktuelle Standard für API-Authentifizierung. API-Keys allein reichen für benutzerbezogene APIs nicht aus.
  • Rate Limiting schützt vor Brute Force, Credential Stuffing und Denial-of-Service. Implementiere es auf mehreren Ebenen: pro IP, pro Benutzer und pro Endpunkt.
  • Input Validation ist die letzte Verteidigungslinie gegen Injection-Angriffe. Validiere Typ, Format, Länge und Wertebereich jeder Eingabe serverseitig.

Warum API-Sicherheit ein eigenes Thema ist

APIs (Application Programming Interfaces) sind die Schnittstellen, über die Anwendungen miteinander kommunizieren. Dein Frontend spricht über eine REST-API mit dem Backend. Dein Backend spricht über APIs mit externen Diensten (Zahlungsdienstleister, E-Mail-Provider, Cloud-Speicher). Deine mobile App nutzt dieselbe API wie dein Web-Frontend.

Das bedeutet: APIs exponieren Geschäftslogik, Daten und Funktionalität. Jeder API-Endpunkt ist ein potenzieller Angriffspunkt. Und anders als eine Weboberfläche, die ein Mensch bedient, werden APIs von Software aufgerufen, was automatisierte Angriffe in großem Maßstab ermöglicht.

Die Angriffsmuster auf APIs unterscheiden sich teilweise von denen auf klassische Webanwendungen. Deshalb hat die OWASP neben den allgemeinen Top 10 eine separate API Security Top 10 veröffentlicht, die speziell auf API-spezifische Risiken eingeht.

OWASP API Security Top 10: Die kritischsten Risiken

Die OWASP API Security Top 10 (Version 2023) identifizieren folgende Risiken:

  1. Broken Object Level Authorization (BOLA): Die API prüft nicht, ob der Benutzer auf das angeforderte Objekt zugreifen darf. Durch Ändern einer ID in der URL kann ein Benutzer auf Daten anderer Benutzer zugreifen.

  2. Broken Authentication: Schwache oder fehlende Authentifizierungsmechanismen. API-Keys, die leicht erraten werden können, fehlende Token-Rotation, kein Schutz gegen Token-Diebstahl.

  3. Broken Object Property Level Authorization: Die API gibt mehr Eigenschaften eines Objekts zurück als nötig (Excessive Data Exposure) oder akzeptiert Eingaben für Eigenschaften, die der Benutzer nicht ändern dürfte (Mass Assignment).

  4. Unrestricted Resource Consumption: Kein Rate Limiting, kein Limit für Request-Größen, kein Limit für Batch-Operationen. Ein Angreifer kann die API mit Anfragen überfluten oder enorme Datenmengen abfragen.

  5. Broken Function Level Authorization: Benutzer können auf API-Endpunkte zugreifen, die für höhere Berechtigungsstufen gedacht sind (z.B. Admin-Funktionen).

  6. Unrestricted Access to Sensitive Business Flows: Automatisierter Missbrauch von Geschäftsfunktionen (z.B. massenhaftes Erstellen von Konten, automatisiertes Aufkaufen von Lagerbeständen).

  7. Server-Side Request Forgery (SSRF): Die API ruft eine vom Benutzer kontrollierte URL ab, was Zugriff auf interne Systeme ermöglicht.

  8. Security Misconfiguration: Fehlende CORS-Konfiguration, detaillierte Fehlermeldungen, unnötige HTTP-Methoden.

  9. Improper Inventory Management: Veraltete API-Versionen, die noch erreichbar sind, undokumentierte Endpunkte, fehlende API-Inventarisierung.

  10. Unsafe Consumption of APIs: Blindes Vertrauen in Daten von Drittanbieter-APIs, ohne sie zu validieren.

Authentifizierung: Wer bist du?

Authentifizierung beweist die Identität des Aufrufers. Die gängigsten Mechanismen für APIs sind API-Keys, OAuth 2.0 und JWTs.

API-Keys

API-Keys sind einfache, zufällig generierte Zeichenketten, die mit jedem Request mitgesendet werden (typischerweise im Header X-API-Key oder als Query-Parameter). Sie identifizieren die aufrufende Anwendung, nicht den einzelnen Benutzer.

Wann API-Keys sinnvoll sind: Server-zu-Server-Kommunikation, bei der eine Anwendung im Namen einer anderen Anwendung handelt (nicht im Namen eines Benutzers). Öffentliche APIs mit Nutzungslimits (der Key identifiziert den Entwickler, nicht den Endbenutzer).

Wann API-Keys nicht reichen: Wenn du wissen musst, welcher Benutzer die Aktion ausführt (z.B. "Benutzer A liest seine eigenen Daten, nicht die von Benutzer B"). API-Keys können das nicht abbilden, weil sie keine Benutzeridentität transportieren.

Sicherheitsmaßnahmen für API-Keys: Generiere Keys mit ausreichender Entropie (mindestens 32 Bytes, zufällig). Übertrage Keys nur über HTTPS. Speichere Keys gehasht in der Datenbank, nicht im Klartext. Implementiere Key-Rotation: Benutzer sollten ihre Keys regelmäßig erneuern können. Vergib unterschiedliche Keys für verschiedene Berechtigungsstufen (Lese-Key, Schreib-Key).

OAuth 2.0

OAuth 2.0 ist der De-facto-Standard für API-Authentifizierung in Szenarien, bei denen ein Benutzer einer Anwendung Zugriff auf seine Daten bei einem anderen Dienst gewährt. Aber auch für eigene APIs ist OAuth 2.0 der empfohlene Ansatz, weil es eine saubere Trennung von Authentifizierung und Autorisierung ermöglicht.

Die wichtigsten OAuth-2.0-Flows sind der Authorization Code Flow mit PKCE (für Web- und Mobile-Apps, bei denen ein Benutzer sich anmeldet), der Client Credentials Flow (für Server-zu-Server-Kommunikation, bei der kein Benutzer involviert ist) und der Device Authorization Flow (für Geräte ohne Browser, z.B. Smart-TVs, CLI-Tools).

Der Implicit Flow und der Resource Owner Password Credentials Flow gelten als veraltet und sollten nicht mehr verwendet werden.

Praxistipp: Verwende einen etablierten Identity Provider (Keycloak, Auth0, Azure AD, AWS Cognito) statt OAuth 2.0 selbst zu implementieren. Die Anbindung über SSO vereinfacht das Identitätsmanagement erheblich. Die korrekte Implementierung ist komplex, und Fehler führen zu schwerwiegenden Sicherheitslücken.

JSON Web Tokens (JWT)

JWTs sind selbstbeschreibende Tokens, die Informationen über den Benutzer (Claims) enthalten und kryptografisch signiert sind. Sie werden häufig als Access Tokens in OAuth-2.0-Implementierungen verwendet.

Sicherheitsmaßnahmen für JWTs: Verwende asymmetrische Signierung (RS256 oder ES256) statt symmetrischer (HS256), weil bei HS256 jeder, der den Schlüssel kennt, auch Tokens erstellen kann. Setze kurze Gültigkeitsdauern (5-15 Minuten für Access Tokens). Validiere die Signatur, den Aussteller (iss), die Zielgruppe (aud) und die Gültigkeitsdauer (exp) bei jedem Request. Verwende alg: none niemals und akzeptiere es nicht (bekannter JWT-Angriff). Speichere keine sensiblen Daten im JWT-Payload, denn JWTs sind nur signiert, nicht verschlüsselt. Der Payload ist Base64-kodiert und für jeden lesbar.

Autorisierung: Was darfst du?

Authentifizierung und Autorisierung sind zwei verschiedene Konzepte, werden aber oft verwechselt oder vermischt. Authentifizierung stellt fest, wer du bist. Autorisierung stellt fest, was du darfst. Beide müssen bei jedem API-Request geprüft werden.

Object-Level Authorization

Prüfe bei jedem Zugriff auf eine Ressource, ob der authentifizierte Benutzer auf genau diese Ressource zugreifen darf. Nicht nur "darf Benutzer A Bestellungen lesen", sondern "darf Benutzer A die Bestellung mit ID 42 lesen".

Das ist die Maßnahme gegen BOLA (Broken Object Level Authorization), das häufigste API-Sicherheitsrisiko. Die Implementierung sieht in der Praxis so aus: Deine Datenbankabfrage filtert immer nach dem aktuell angemeldeten Benutzer. Statt SELECT * FROM orders WHERE id = ? schreibst du SELECT * FROM orders WHERE id = ? AND user_id = ?. Dadurch ist es technisch unmöglich, auf fremde Daten zuzugreifen, egal was der Benutzer in der URL ändert.

Function-Level Authorization

Prüfe bei jedem Endpunkt, ob der Benutzer die nötige Rolle oder Berechtigung hat. Admin-Endpunkte müssen prüfen, ob der Benutzer ein Administrator ist. Management-Endpunkte müssen prüfen, ob der Benutzer ein Manager ist.

Implementiere die Autorisierung als Middleware oder Decorator, nicht in jedem Controller einzeln. Ein zentraler Autorisierungsmechanismus ist leichter zu warten und schwerer zu vergessen.

Principle of Least Privilege

Gib API-Clients nur die minimal notwendigen Berechtigungen. OAuth-2.0-Scopes eignen sich hervorragend dafür: Ein Client, der nur Daten lesen muss, bekommt den Scope read:orders. Ein Client, der auch schreiben muss, bekommt zusätzlich write:orders. Ein Client, der Benutzer verwalten muss, bekommt admin:users.

Rate Limiting: Missbrauch verhindern

Rate Limiting begrenzt die Anzahl der Anfragen, die ein Client in einem definierten Zeitraum senden darf. Es schützt vor verschiedenen Angriffsarten.

Warum Rate Limiting unverzichtbar ist

Brute-Force-Angriffe: Ohne Rate Limiting kann ein Angreifer tausende Login-Versuche pro Sekunde durchführen und Passwörter durch Ausprobieren erraten.

Credential Stuffing: Der Angreifer testet automatisiert gestohlene Zugangsdaten (aus Datenlecks) gegen deine API. Multi-Faktor-Authentifizierung bietet zusätzlichen Schutz. Bei Millionen von Zugangsdaten in der Liste ist Rate Limiting der einzige Schutz.

Denial of Service: Ohne Rate Limiting kann ein einzelner Client die API mit so vielen Anfragen überfluten, dass sie für alle anderen Benutzer unbenutzbar wird.

Datenexfiltration: Ein kompromittierter API-Key wird verwendet, um die gesamte Datenbank über die API auszulesen. Rate Limiting begrenzt die Menge der Daten, die pro Zeiteinheit abgefragt werden können.

Implementierungsstrategien

Festes Fenster (Fixed Window): Maximal N Requests pro Minute. Einfach zu implementieren, hat aber einen Nachteil: An der Grenze zweier Zeitfenster können kurzzeitig 2N Requests durchkommen (N am Ende des einen Fensters, N am Anfang des nächsten).

Gleitendes Fenster (Sliding Window): Behebt den Grenzfall des festen Fensters, indem ein gleitender Zeitraum betrachtet wird. Komplexer zu implementieren, aber genauer.

Token Bucket: Jeder Client hat einen "Eimer" mit Tokens. Jeder Request verbraucht ein Token. Der Eimer wird mit einer festen Rate aufgefüllt. Wenn der Eimer leer ist, werden Requests abgelehnt. Erlaubt kurze Bursts (der Eimer kann voll sein), begrenzt aber den Durchschnitt.

Leaky Bucket: Ähnlich wie Token Bucket, aber Requests werden gleichmäßig abgearbeitet, nicht in Bursts. Für APIs, die gleichmäßige Last bevorzugen.

Mehrstufiges Rate Limiting

Implementiere Rate Limiting auf mehreren Ebenen.

Global: Maximal 10.000 Requests pro Minute für die gesamte API (schützt vor DDoS).

Pro IP: Maximal 100 Requests pro Minute pro IP-Adresse (schützt vor einzelnen Angreifern).

Pro Benutzer: Maximal 60 Requests pro Minute pro authentifiziertem Benutzer (schützt vor kompromittierten Accounts).

Pro Endpunkt: Sensible Endpunkte (Login, Passwort-Reset) haben strengere Limits als lesende Endpunkte. z.B. Login: maximal 5 Versuche pro Minute, Daten lesen: maximal 100 Requests pro Minute.

HTTP-Header für Rate Limiting

Informiere den Client über die geltenden Limits mit standardisierten HTTP-Headern: X-RateLimit-Limit (maximale Requests im Zeitfenster), X-RateLimit-Remaining (verbleibende Requests), X-RateLimit-Reset (Zeitpunkt, an dem das Fenster zurückgesetzt wird) und Retry-After (Wartezeit in Sekunden, wenn das Limit erreicht ist).

Wenn das Limit erreicht ist, antworte mit HTTP 429 (Too Many Requests).

Input Validation: Vertraue keiner Eingabe

Input Validation ist die grundlegendste und gleichzeitig am häufigsten fehlende Sicherheitsmaßnahme. Jede Eingabe, die deine API empfängt, ob aus dem Body, den Query-Parametern, den Headern oder dem Path, ist potenziell bösartig und muss validiert werden.

Validierungsebenen

Typvalidierung: Ist die Eingabe vom erwarteten Typ? Wenn du eine Zahl erwartest, stelle sicher, dass die Eingabe tatsächlich eine Zahl ist und kein String mit SQL-Code.

Formatvalidierung: Entspricht die Eingabe dem erwarteten Format? E-Mail-Adressen, Telefonnummern, Datumsangaben, UUIDs haben definierte Formate.

Wertebereichsvalidierung: Liegt die Eingabe im gültigen Bereich? Ein Alter sollte zwischen 0 und 150 liegen, nicht bei -1 oder 999999.

Längenvalidierung: Ist die Eingabe nicht zu lang? Ein Name mit 10.000 Zeichen ist wahrscheinlich kein Name, sondern ein Angriff.

Business-Logic-Validierung: Ist die Eingabe im Geschäftskontext gültig? Eine Bestellmenge von -5 sollte abgelehnt werden, auch wenn -5 eine gültige Zahl ist.

Schema-Validierung

Für REST-APIs mit JSON-Payloads ist JSON Schema ein mächtiges Werkzeug zur Eingabevalidierung. Du definierst ein Schema, das die erwartete Struktur, Typen, Formate und Wertebereiche beschreibt, und validierst jeden eingehenden Request gegen dieses Schema.

Wenn du eine OpenAPI-Spezifikation (Swagger) für deine API hast, kannst du die darin definierten Schemata direkt zur Validierung verwenden. Tools wie express-openapi-validator (Node.js), connexion (Python) oder OpenAPI-Middleware für andere Frameworks übernehmen die Validierung automatisch.

Sanitisierung vs. Validierung

Validierung prüft, ob die Eingabe gültig ist, und lehnt sie bei Ungültigkeit ab. Sanitisierung verändert die Eingabe, um sie "sicher" zu machen (z.B. HTML-Tags entfernen). Bevorzuge Validierung vor Sanitisierung. Wenn eine Eingabe ungültig ist, lehne sie ab, statt zu versuchen, sie zu reparieren. Sanitisierung kann zu unerwartetem Verhalten führen und ist fehleranfälliger.

API-Sicherheit in der Praxis: Checkliste

Hier eine kompakte Checkliste, die du für jede API durchgehen kannst.

Authentifizierung: Jeder Endpunkt erfordert Authentifizierung (außer explizit öffentliche Endpunkte). OAuth 2.0 oder API-Keys (je nach Anwendungsfall). Token-Gültigkeitsdauer angemessen kurz.

Autorisierung: Object-Level-Authorization bei jedem Datenzugriff. Function-Level-Authorization bei jedem Endpunkt. Least Privilege für API-Clients und Scopes.

Rate Limiting: Globales Limit, Pro-IP-Limit, Pro-Benutzer-Limit. Strengere Limits für sensible Endpunkte. HTTP-429-Antworten mit Retry-After-Header.

Input Validation: Alle Eingaben validiert (Typ, Format, Länge, Wertebereich). Schema-Validierung für JSON-Payloads. Keine Annahme, dass das Frontend validiert hat.

Transportverschlüsselung: HTTPS überall. TLS 1.2 oder höher. HSTS-Header. Deine Verschlüsselungsstrategie sollte die Standards verbindlich festlegen.

Error Handling: Keine Stack Traces oder interne Details in Fehlermeldungen. Standardisierte Fehlerantworten (z.B. RFC 7807 Problem Details). Fehler loggen, aber dem Client nur allgemeine Informationen geben.

Logging und Monitoring: Alle authentifizierungsrelevanten Events loggen. Anomalien erkennen (ungewöhnlich viele Requests, Zugriff auf fremde Daten). Alerting bei verdächtigen Mustern.

Dokumentation: Alle Endpunkte dokumentiert (OpenAPI/Swagger). Authentifizierungsanforderungen dokumentiert. Veraltete Endpunkte deprecaten und nach einer Übergangsphase abschalten.

API-Sicherheit und regulatorische Anforderungen

APIs sind kein isoliertes Technikthema. Sie fallen unter die allgemeinen Anforderungen an sichere Entwicklung und Betrieb.

NIS2 fordert sichere Entwicklungspraktiken (Artikel 21, Absatz 2e), und APIs sind ein wesentlicher Teil jeder modernen Anwendung. ISO 27001 Annex A, Kontrolle A.8.26 (Application security requirements), fordert, dass Sicherheitsanforderungen für Anwendungen identifiziert und umgesetzt werden. Eine API-Sicherheitsrichtlinie, die Authentifizierung, Autorisierung, Rate Limiting und Input Validation adressiert, ist der Nachweis, dass du diese Anforderung für deine APIs erfüllst. In ISMS Lite lässt sich die API-Sicherheitsrichtlinie mit Authentifizierungsstandards und Prüfpunkten zentral dokumentieren und mit den ISO-27001-Controls verknüpfen.

API-Versionierung und Lifecycle

APIs entwickeln sich weiter. Neue Endpunkte kommen hinzu, bestehende ändern sich, alte werden obsolet. Ohne eine klare Versionierungsstrategie riskierst du, dass veraltete und möglicherweise unsichere API-Versionen weiterbetrieben werden, weil Clients noch darauf zugreifen.

Die gängigsten Versionierungsstrategien sind URL-basierte Versionierung (/api/v1/users, /api/v2/users), Header-basierte Versionierung (Accept: application/vnd.myapi.v2+json) und Query-Parameter-Versionierung (/api/users?version=2). URL-basierte Versionierung ist die am weitesten verbreitete und einfachste Variante.

Für die Sicherheit ist entscheidend, dass du alte API-Versionen nach einer definierten Übergangsphase abschaltest. Eine API-Version, die seit zwei Jahren nicht mehr gepflegt wird, enthält möglicherweise Schwachstellen, die in neueren Versionen längst behoben sind. Dokumentiere den Lifecycle jeder API-Version: Einführungsdatum, Deprecation-Datum, End-of-Life-Datum.

API-Gateway als zentrale Sicherheitsschicht

Ein API-Gateway ist ein Reverse Proxy, der vor deinen API-Servern steht und zentrale Sicherheitsfunktionen übernimmt: Authentifizierung, Rate Limiting, IP-Whitelisting, Request-Validierung, Logging und TLS-Terminierung.

Gängige API-Gateways sind Kong (Open Source, Plugin-Architektur), Traefik (Open Source, gut für Container/Kubernetes), AWS API Gateway (Managed Service), Azure API Management (Managed Service) und NGINX (als Reverse Proxy mit Lua-Erweiterungen).

Der Vorteil eines API-Gateways: Du implementierst Sicherheitsfunktionen einmal zentral statt in jeder API einzeln. Wenn du Rate Limiting oder Authentifizierung ändern musst, änderst du es am Gateway, nicht in 20 verschiedenen Microservices.

Weiterführende Artikel

API-Sicherheitsrichtlinie dokumentieren

ISMS Lite hilft dir, deine API-Sicherheitsrichtlinie zu dokumentieren, Authentifizierungsstandards festzulegen und die Einhaltung für Audits nachzuweisen.

Jetzt installieren