Beim Entwickeln moderner Software spielen Web APIs eine immer wichtigere Rolle. Single Page Webapplikationen, wie sie häufig in Enterprise- und B2B-Umgebungen angetroffen werden und meist mit Technologien wie Angular und VueJS entwickelt sind, setzen ausschliesslich auf Web APIs. Deshalb beschäftigen wir uns immer stärker mit den Sicherheitsaspekten solcher – und anderer – APIs.
Die Titel der einzelnen Probleme sind direkt dem OWASP Dokument entnommen und wurden nicht übersetzt, da die Titel von den Autoren sehr bewusst gewählt wurden und eine Übersetzung die ursprüngliche Bedeutung verwässern könnte.
Bei einer typischen Abfrage einer API wird eine bestimmte Resource eines bestimmten (manchmal externen) Services abgefragt oder es werden Aktionen auf einer solchen Resource vorgenommen. Jeder Service, der solche APIs bereitstellt, sollte überprüfen, ob die jeweiligen Benutzer:innen, die eine solche Anfrage durchführend, dies überhaupt dürfen.
Als Beispiel soll ein Service dienen,
der von verschiedenen Benutzer:innen genutzt wird.
Alle Benutzer:innen können ihr eigenes Profil über /user/{userId}
abrufen.
Also ein Benutzer mit der ID 11
darf auf die Informationen unter /user/11
zugreifen.
Die Benutzerin mit der ID 12
darf hingegen die Informationen unter /user/11
nicht sehen.
Es gibt jedoch Services,
die keine solche fein-granulare Überprüfung der Berechtigungen vornehmen.
Diese verlangen dann zum Beispiel einfach eine gültige Anmeldung,
um auf /user/*
zuzugreifen.
Im beschriebenen Fall wäre dies aber falsch,
und genau dies ist,
was dieses erste Problem beschreibt.
Das Problem 5 weiter unten ist ähnlich wie dieses.
Oft dürfen nur authentifizierte Benutzer:innen auf eine API zugreifen. Dann müssen sich Benutzer:innen irgendwie bei der API anmelden. Dieses zweite Problem beschreibt typische Szenarien, die bei der Implementation oder Konfiguration des Authentifizierungs-Mechanismuses nicht bedacht wurden.
Zu solchen Schwachstellen-Szenarien gehören:
Ein ähnlich gelagertes Beispiel besteht mit dem HTTP Header X-Forwarded-For
.
Oft werden solche Header am Rand des eigenen Systems nicht aus den eingehenden Requests entfernt.
Trotzdem werden diese dann im
Backend eingesetzt,
um beispielsweise IP-basierte Authorisierung zu implementieren.
Wenn nun Absender*innen von
API-Requests den X-Forwarded-For
Header
(oder andere Header mit ähnlichem Zweck) selber beeinflussen können,
dann können diese so die Sicherheitsmassnahmen umgehen.
Dieses dritte Problem legt das Augenmerk auf unbeabsichtigt gesendete Informationen oder solche, die mit unbeabsichtigt hohem Detailgrad bereitgestellt werden.
Als Beispiel soll eine Dating App dienen. Die möglichen Dating-Kandidat:innen werden von der API zurückgeliefert. Als Information zur Berechnung der Distanz dienen die Koordination des aktuellen Standorts der Kandidat:innen. In der App wird der genaue Ort der Kandidat:innen gar nicht dargestellt. Obwohl die Information im UI gar nicht dargestellt wird, können technisch versierte Benutzer:innen die Information trotzdem aus der API auslesen und so den genauen aktuellen Standort der anderen Nutzer:innen dieser App rekonstruieren. Die Standortinformation ist also unnötig genau. Es würde auch reichen, wenn der Standort nur ungenau (bsp. auf 100m genau) gesendet würde. Oder wenn der Server gleich selber die Berechnung der Distanz übernehmen würde und nur dies der Client-Applikation zurückmelden würde.
API Requests benötigen Server Ressourcen, die durch die Betreiber:innen bereitgestellt werden müssen. Gerade auf Cloud-Plattformen werden diese Ressourcen sehr direkt mit Geld aufgewogen. Aber auch herkömmliches Hosting ist selten gratis.
Es ist deshalb im Eigeninteresse aller API Service Betreiber:innen, die zur Verfügung stehenden Ressourcen zu begrenzen. Selbst wenn die Kund:innen pro Request bezahlen ist es sinnvoll, diese vor sich selber zu schützen. Denn schnell ist in einem Script etwas verändert, was versehentlich viele Requests auf den Service auslöst.
Dinge, die dazu beachtet werden sollten:
Einige dieser Limits und Empfehlungen können beim Einsatz von Container-Technologie (wie Docker oder Kubernetes) relativ einfach definiert werden. Andere können oft mittels eines API Gateways oder einer Service Mesh-Software umgesetzt werden. Und einige müssen hingegen direkt im Code der Applikation umgesetzt werden.
Dieses Problem beschreibt,
dass Benutzer:innen nur Zugriff auf die
API Endpoints haben sollten,
für die sie auch zugelassen sind.
Beispielsweise gibt es wieder den Benutzer mit der ID 11
, der Informationen zu seinem Profil unter /user/11
abrufen kann.
Er sollte jedoch keinen Zugriff auf die
API /users
haben,
wo alle Benutzer:innen aufgelistet werden.
Das Problem ist ganz ähnlich dem Problem 1 vom Anfang. Dasjenige Problem beschreibt jedoch den Zugriff auf den gleichen Endpoint, also zum Beispiel
/user/11
vs./user/12
. Das vorliegende Problem hingegen beschreibt den Zugriff auf verschiedene Ressourcen, also hier/user/11
vs./users
.
Dieses Problem beschreibt, dass Benutzer:innen unter Umständen Informationen über die API verändern können, die sie eigentlich verändern dürften.
Typischerweise haben zum Beispiel Benutzer:innen in Applikationen eine eindeutige ID. Und während Benutzer:innen nun ihre eigene E-Mail Adresse anpassen dürfen, sollte es ihnen nicht möglich sein, ihre ID zu verändern.
Dieses Problem beschreibt typische Sicherheitsprobleme bei Software. Dazu gehören:
index.html
(oder entsprechende) Datei besteht.Dieses Problem beschäftigt sich mit Daten ausserhalb des Systems, die beispielsweise durch Benutzer:innen oder Drittsysteme bereitgestellt werden. Solchen Informationen darf grundsätzlich nicht vertraut werden. Es müssen Massnahmen getroffen werden, dass solche Informationen keine applikationsinterne Befehle modifizieren können. Modifikationen dieser Art werden generell als Injections bezeichnet. Es gibt verschiedene Arten solcher Injections, zum Beispiel SQL Injections, Betriebssystem-Kommando Injections oder HTML injections (auch bekannt als Cross Site Scripting, XSS).
Konkrete Beispiele sind:
X-Forwarded-For
sollte generell vom ersten Server,
der einen HTTP Request empfängt,
entfernt werden.
Beispielsweise könnte es sein,
dass der Inhalt eines Header als Parameter für eine Script genutzt wird.
Werden solche Header nicht entfernt
– und ohne weitere Massnahmen –
könnten in diesem Beispiel Benutzer:innen beliebige Befehle auf den entsprechenden Servern ausführen.Dies ist eher ein organisatorisches Problem, was die Behandlung nicht unbedingt einfacher macht.
Es beschreibt, dass Organisationen oft keine gute Übersicht über die API(-Versionen) haben, die sie aktuell betreiben. Auch wissen sie manchmal nicht so genau, wie sie die unterschiedlichen API schützen.
An dieser Stelle ein Beispiel aus dem ursprünglichem OWASP Dokument:
Es wird beschrieben, dass ein bestimmtes
API über eine URL erreichbar ist, zum Beispiel myservice.example/api
.
Parallel dazu wird eine Entwicklungsversion unter beta.myservice.example/api
betrieben.
Im Gegensatz zur produktiven
API ist die Entwicklungsversion nicht durch das gleiche Anti-Bruteforce Gateway geschützt
und wir auch nicht gleich gut überwacht.
Trotzdem enthält es ähnliche Daten wie das produktive
API,
weil gelegentlich die produktiven Benutzer:innen in die Entwicklungsversion importiert werden.
Angreifer:innen,
die dies herausfinden,
können nun ihren Angriff auf der Entwicklungsumgebung durchführen.
Sobald die entsprechenden Anmeldedaten herausgefunden wurden,
kann damit auf die produktive Umgebung zugegriffen werden.
Meiner Erfahrung nach entsteht dieses Problem vor allem dann, wenn der Betrieb einer Applikation (oder in diesem Fall der API) nur als Nebenleistung am Ende des Projekts angesehen wird. Das Entwicklungsteam sieht es nicht als seine Aufgabe an, an den Betrieb der Applikation zu denken und es wurde auch nicht dazu verdonnert, sich bereits früh in der Entwicklung mit dem Betriebspersonal abzusprechen.
Logdateien sind besonders wichtig,
wenn im Nachhinein herausgefunden werden soll,
wieso etwas so abgelaufen ist,
wie es abgelaufen ist.
Dies gilt insbesondere,
wenn eine laufende Attacke abgewehrt werden soll
oder eine bereits abgelaufene Attacke nachvollzogen werden muss.
Inkorrekt konfiguriertes Logging kann jedoch einen Server auch lahmlegen.
Beispielsweise wenn alles auf dem TRACE
Level geloggt wird und sich so die Disk füllt.
Oder nur schon,
wenn das so viele Logdaten generiert und damit so viele IO-Operationen auf dem Server verursacht,
dass andere Prozesse ihre Dateien nicht mehr oder nur stark verzögert lesen oder schreiben können.
Viele dieser Probleme werden nicht bewusst geschaffen und das Verhindern dieser ist eigentlich gesunder Menschenverstand. Aber dazu müssen die Entwickler:innen und Betreiber:innen schon einmal von den entsprechenden Problemen gehört haben. Zumindest wir sind uns diesen Problemen bewusst und versuchen, diese bei unseren Applikationen zu vermeiden.
Ich kann allen Leser:innen empfehlen, sich auch mit dem Originaldokument zu befassen. Es enthält weitere illustrierende Beispiele sowie die detaillierten Beschreibungen jedes Problems. Das Originaldokument kann kostenlos vom entsprechenden GitHub Repository bezogen werden.