API-Sicherheit – Grundlagen und Best Practices
Regelmäßige Leser unseres Blogs wissen, dass APIs einen zentralen Erfolgsfaktor moderner IT-Organisationen ausmachen. Wenn wir API-Entwurf, API-Management und API-Strategie richtig angehen, erlauben APIs es uns kostengünstig und reibungsfrei Systeme zu integrieren, Teams in ihrer Effektivität und Effizienz zu skalieren, und Innovation zu fördern.
Und doch birgt der Erfolgsfaktor „APIs“ auch Gefahren. Per Definition gibt eine solche Schnittstelle etwas preis, sie ermöglicht einen Zugriff. Eine verwundbare Schnittstelle nach „außen“ kann von einem Angreifer genutzt werden, Interna auszuspähen, zu manipulieren oder sogar in unser Netz einzudringen. Eine verwundbare interne Schnittstelle bietet einem Angreifer, der bereits in unsere Organisation eingedrungen ist, potenziell die Möglichkeit, sich „lateral“ zu bewegen, also auf weitere Systeme und in weitere Schutzzonen einzudringen. Und als wäre dies nicht bereits schlimm genug, handelt es sich bei einer API eben um eine Programmierschnittstelle, was bedeutet, dass wir Angreifern die Automatisierbarkeit ihrer Angriffe direkt mitliefern.
Diesen Gefahren können wir allerdings nicht entgegentreten, indem wir auf APIs verzichten, denn schließlich wollen wir sie uns ja als Erfolgsfaktor zu Nutze machen. Und schlussendlich entstehen Schnittstellen ohnehin, egal ob wir sie planen oder nicht, immer dann, wenn wir Systeme integrieren. Der Unterschied besteht nur darin, dass ungeplant entstehende Schnittstellen mit hoher Wahrscheinlichkeit undurchdacht, ineffizient, fehleranfällig und kostspielig sind, sowie die größtmöglichen Sicherheitsrisiken mit sich bringen.
Die einzig praktikable Lösung liegt auf der Hand: der Entwurf jeder API muss immer auch einhergehen mit einem geeigneten API-Security-Konzept, ganz im Sinne des Prinzips „Shift-left-Security“: es gilt, die Sicherheit von Anfang an mitzudenken — und zwar auf allen Betrachtungsebenen. Nachfolgend diskutieren wir einige Grundlagen, Maßnahmen und Regel, die es dabei zu beachten lohnt. Der Fokus liegt dabei auf APIs, die über das HTTP-Protokoll konsumiert werden, wobei viele der diskutierten Konzepte auch über HTTP-APIs hinaus Gültigkeit haben.
Grundlagen der API-Sicherheit - Die Basics
„Security by Design“ mag zunächst nach einer Herausforderung klingen. In Wahrheit ist API-Security jedoch kein Hexenwerk, sobald man einige Grundprinzipien verinnerlicht hat.
Dimensionen der IT-Sicherheit – Die CIA-Triade
Diese Triade müssen wir auch bei der Beurteilung des Schutzbedarfs unserer APIs und der dafür erforderlichen Maßnahmen berücksichtigen. Denn während manche Maßnahmen geeignet sind, auf mehrere dieser Dimensionen gleichzeitig einzuzahlen, fokussieren andere Maßnahmen nur einzelne Aspekte. Beispielsweise sind Lastverteilung und Clustering gängige Maßnahmen, die zu einer höheren Verfügbarkeit beitragen können, aber keinen Beitrag zur Vertraulichkeit liefern. Darüber hinaus sind Bedrohungsszenarien und Schutzbedarf in der Regel in den einzelnen Dimensionen unterschiedlich stark ausgeprägt. Beispielsweise könnte es sein, dass die API eines öffentlichen Branchenverzeichnisdienstes nur geringen Schutzbedarf hinsichtlich der Vertraulichkeit erfordert, dafür aber einen sehr hohen Schutzbedarf hat hinsichtlich der Integrität.
- Wir müssen uns also stets folgende Fragen stellen:
- Welcher Schaden entsteht, wenn ein Angreifer unbefugt Einsicht in vertrauliche Daten erlangt?
- Welcher Schaden entsteht, wenn ein Angreifer unbefugt Daten verändert?
- Welcher Schaden entsteht, wenn ein Angreifer die Verfügbarkeit unserer API beeinträchtigt?
- Welche Maßnahmen stehen uns zur Verfügung, um das Eintrittsrisiko dieser Schäden zu verringern?
- Authentifizierung (AuthN) – Methoden und Best Practices für APIs
Wer wird unsere API nutzen und wie können wir die Identität unserer Nutzer prüfen? Wer glaubt, dass diese Frage nur relevant ist, wenn Funktionen oder Daten nur berechtigten Benutzern zugänglich sein dürfen, irrt (und verwechselt Authentifizierung mit Autorisierung).
- Ohne Authentifizierung wird es uns schwerfallen, nach einem Sicherheitsvorfall Verantwortliche zu identifizieren.
- Ohne Authentifizierung ist kein präzises, nutzerbezogenes Rate-Limiting möglich, sodass entweder das Rate-Limit umgangen werden kann oder bei einer Limit-Überschreitung durch Einzelne auch Dritte mit ausgesperrt werden.
- Auch über reine Sicherheitsaspekte hinaus gibt es oft Gründe, die dafürsprechen, APIs von Anfang an authentifiziert zu entwerfen:
- Fachliche Funktionen der API könnten bereits jetzt oder in Zukunft einen Benutzerbezug erfordern.
- Kontingentierung, Monetarisierung und die Erstellung unterschiedlicher Nutzungspläne und Service-Level erfordern einen Benutzerbezug.
- Zukünftige Erweiterungen um autorisierte Funktionalitäten werden Authentifizierung erfordern.
Authentifizierung bildet somit die Grundlage für zahlreiche Maßnahmen für Vertraulichkeit, Integrität und sogar Verfügbarkeit unserer APIs. Daher sind in der Praxis kaum Ausnahmen vorstellbar, bei denen nicht zumindest eine grundlegende Authentifizierung erforderlich ist.
Einige gängige Authentifizierungsmechanismen für APIs sind:
- API-Keys: API-Keys sind eine weit verbreitete und sehr einfache Methode für die Authentifizierung an APIs, die jedoch meist mit einigen Schwächen einhergeht: API-Keys sind in der Regel in erster Linie für die Authentifizierung von Service-Nutzern, nicht individuellen Benutzern konzipiert. Es fehlen oft Standardmechanismen und Antworten auf wichtige Fragestellungen, wie Rotation, sicherer Aufbewahrung und sicherer Übertragung.
- mTLS (mutual TLS): mTLS ist ein erprobter, sehr sicherer Authentifizierungsstandard. Allerdings ist für den Einsatz von mTLS ein grundlegendes Verständnis von asymmetrischer Kryptographie erforderlich. Darüber hinaus ist das häufig gewünschte Weiterreichen des Benutzerkontexts über mehrere transitive Service-Aufrufe hinweg nicht ohne Weiteres mit mTLS möglich. Auch das erforderliche Zertifikatsmanagement stellt manche Organisationen vor Herausforderungen.
- OAuth2 / OpenID Connect (OIDC): OAuth2 und das darauf aufbauende OIDC sind inzwischen weit verbreitete Standards für Token-basierte Authentifizierung geworden. Support für diese Standards ist in allen gängigen Programmierframeworks vorhanden. Darüber hinaus entkoppelt OAuth2 viele komplizierte Aspekte von Authentifizierung (und Autorisierung) von unseren APIs und ermöglicht es uns, die Umsetzung dieser Aspekte auszulagern in erprobte, „von der Stange“ verfügbare Produkte.
Natürlich gibt es neben den genannten Mechanismen weitere Verfahren zur Authentifizierung. Gerade innerhalb bestimmter abgegrenzter Ökosysteme, wie etwa den Cloud-Angeboten populärer Hyperscaler, sind oft herstellerspezifische Lösungen verfügbar und einfach einsetzbar. Die oben aufgeführten Methoden, insbesondere OAuth2, zeichnen sich jedoch durch große Portabilität und Herstellerunabhängigkeit aus.
Autorisierung (AuthZ) – Zugriffskontrolle für APIs
Ist der authentifizierte Benutzer berechtigt, einen gegebenen API-Aufruf durchzuführen, und welche Informationen ist dieser Benutzer berechtigt, als Antwort auf seine Anfrage zu erhalten? Die Antworten auf diese Fragen zeigen uns, wie wir mithilfe von Autorisierung Vertraulichkeits- und Integritätsanforderungen unserer APIs adressieren. Einige gängige Autorisierungskonzepte sind:
- Role-Based Access Control (RBAC): Bei RBAC werden Benutzern Rollen zugeordnet. Verschiedenen Rollen können verschiedene Berechtigungen zugewiesen werden. Rollen sind oft mit geringerem Aufwand zu verwalten als individuelle Benutzerberechtigungen und ergeben sich meist auf sehr natürliche Weise aus fachlichen Benutzergruppen. RBAC adressiert jedoch nicht Fälle, in denen Berechtigungsanforderungen mit individuellem Personenbezug vorliegen, beispielsweise wenn die API ihren Benutzern die Selbstverwaltung ihrer eigenen Daten ermöglichen soll.
- Attribute-Based Access Control (ABAC): Bei ABAC kommen auf verschiedenen Attributen basierende Zugriffsberechtigungsregeln zum Einsatz. Beispielsweise könnte ein Zugriff nur zu bestimmten Zeiten, von bestimmten Standorten aus, mit bestimmten Authentifizierungsarten (z.B. nur mit 2FA) zulässig sein.
- dentitätsbasierte Zugriffskontrolle: Identitätsbasierte Zugriffskontrolle erlaubt die Unterscheidung der Zugriffsberechtigungen unterschiedlicher Benutzeridentitäten. Damit ist es beispielsweise möglich, dass zwei unterschiedliche Benutzer über dieselbe API-Funktion unterschiedliche Daten abrufen können, die ihnen jeweils individuell zugeordnet sind, etwa bei einer Funktionalität wie dem Abruf von durch den jeweiligen Benutzer selbst erstellten Ressourcen.
In der Praxis ist es meist sinnvoll, je nach Use-Case unterschiedliche Mechanismen einzusetzen und sie gegebenenfalls auch zu kombinieren. Natürlich existieren neben den genannten Autorisierungskonzepte weitere Konzepte, die hier nicht erschöpfend aufgeführt werden sollen. Wird ein Token-basierter Authentifizierungsmechanismus eingesetzt, bieten sich die enthaltenen Claims als Autorisierungsinformationen an. Dabei kann es sich um sogenannte Scopes handeln, aber natürlich können mittels der Claims auch Benutzeridentitäten, Rollen und weitere Attribute transportiert und durch die API zur Autorisierung ausgewertet werden.
Kryptografie in der API-Sicherheit
Ein weiteres Grundkonzept der IT-Sicherheit, das wir zur Absicherung unserer APIs benötigen, ist die Verschlüsselung von Daten und Kommunikation. Dabei sollte TLS 1.3 als Basisanforderung für HTTP-basierte APIs als gesetzt gelten, um eine sichere Kommunikation zu gewährleisten.
Aber auch darüber hinaus spielen kryptographische Verfahren eine wichtige Rolle. Kryptographische signierte Nachrichten ermöglichen es uns, die Authentizität einer Nachricht sicherzustellen, wie beispielsweise bei mTLS zur Clientauthentifizierung. Während (m)TLS nur einen Kommunikationskanal absichert, der aber häufig bereits an einem API-Gateway terminiert wird, kann in Szenarien mit hohen Vertraulichkeitsanforderungen auch eine Ende-zu-Ende-Verschlüsselung von Nachrichteninhalten umgesetzt werden. Neben der Betrachtung von Maßnahmen zur verschlüsselten Kommunikation („Encryption-in-Transit“) kann auch eine Betrachtung von „Encryption-at-Rest“ sinnvoll sein: Die verschlüsselte Ablage von Daten ist eine Maßnahme, mit der Daten vor unbefugtem Auslesen (und, falls auch Signaturen eingesetzt werden, vor unbefugter Manipulation) aus Datenspeichern wie Datenbanken zu schützen.
Rate-Limiting – Schutz vor Überlastung und Missbrauch
Rate-Limiting ist eine Technik zur Begrenzung der Anzahl von API-Anfragen innerhalb eines bestimmten Zeitraums. Sie dient dazu, die Stabilität, Sicherheit und Fairness der API-Nutzung sicherzustellen und zahlt insbesondere auf die Verfügbarkeit unserer APIs ein. Wichtig ist dabei, Zugriffe möglichst so zu tracken, dass jeweils eigene „Töpfe“ für individuelle Benutzer gebildet werden, damit die Rate-Limits präzise angewendet werden können. Ansonsten führt möglicherweise die Durchsetzung der Zugriffsbegrenzung bei einer übermäßigen Nutzung durch einen Nutzer dazu, dass andere Nutzer mitausgesperrt werden, nichts anderes als eine „Denial-of-Service“-Verwundbarkeit (DoS) darstellt und damit das Gegenteil von „Verfügbarkeit“ erreicht
.
Wie auch bei den vorigen Maßnahmen, kann es auch bei Rate-Limits häufig sinnvoll sein, auch innerhalb einer API unterschiedliche Regeln umzusetzen, je nach Funktion, Use-Case und Schutzbedarf.
Fazit und nächste Schritte in der API-Sicherheit
Bereits die aufgeführten Grundlagen befähigen uns, notwendige und wirksame Maßnahmen für die Sicherheit unserer APIs zu ergreifen:
- Mittels der CIA-Triade sind wir in der Lage, den Schutzbedarf einer API zu bewerten und informierte Risikoabwägungen durchzuführen.
- Der Einsatz etablierter Standardkonzepte zur Authentifizierung ermöglicht es uns, sicherzustellen, dass es sich bei den auf die API zugreifenden Benutzern auch wirklich um jene handelt, die sie vorgeben zu sein.
- Der Einsatz etablierter Standardkonzepte zur Autorisierung ermöglicht es uns, sicherzustellen, dass es Benutzer genau die Aktionen durchführen und Informationen einsehen können, auf die sie berechtigt sind.
- Kryptographische Verfahren bieten uns eine Vielzahl an Funktionen zur Absicherung unserer APIs, wie beispielsweise vertrauliche und identitätsgesicherter Übertragung und Speicherung von Informationen.
- Mit Hilfe von Rate Limiting können wir gezielt steuern, wieviel Last wir bereit sind, von einer Quelle aufzunehmen. Diese Maßnahme hilft uns, Beeinträchtigungen der Verfügbarkeit unserer API durch Nutzer mit unerwünschtem oder zumindest unerwartetem Lastverhalten zu begrenzen.
Uns muss allerdings bewusst sein, dass uns die bloße Kenntnis dieser Grundlagen der API-Sicherheit keineswegs zu Sicherheitsexperten macht. Der erfolgreiche Einsatz der genannten Maßnahmen muss mit der Erkenntnis einhergehen, dass die allermeisten von uns nicht qualifiziert sind, sie von Grund auf selbst umzusetzen. Die korrekte Umsetzung von Sicherheitsmechanismen „im Eigenbau“ kann teuflisch kompliziert sein. Stattdessen sollten wir möglichst immer auf etablierte, erprobte Standardlösungen zurückgreifen, um Fehler zu vermeiden. Dafür können wir dann unsere Aufmerksamkeit den Aspekten widmen, die uns eine generische Lösung nicht abnehmen kann, nämlich die Auswahl der geeigneten Mechanismen für die Anwendungsfälle unserer APIs und ihr Zusammenspiel im Ökosystem, indem unsere API existiert.
Es ist wichtig, zu verstehen, in welchem Umfeld unsere API platziert ist und welche Wechselwirkungen im Hinblick auf die API-Security existieren, um zu erkennen, wie wir uns diese Wechselwirkungen zu Nutze machen können. Daher wollen wir in einem weiteren Blogpost näher auf dieses Thema eingehen.