Server Side Request Forgery
Server Side Request Forgery
Server Side Request Forgery (SSRF) ist eine Lücke in Webapplikationen, bei der der Angreifer die serverseitige Anwendung dazu bringt eine Anfrage an ein beliebiges Ziel auszuführen. Häufig tritt diese Lücke auf, wenn Benutzer eine URL an die Anwendung übergeben können und die Anwendung diese URL abfragt, um Informationen für den Benutzer abzuholen. Beispiele wären die Abfrage von RSS-Feeds, Aktienkurse oder das "Hochladen" von Bildern in eine Anwendung über die Angabe einer URL.
In diesem Fall übermittelt der Benutzer eine URL im Query-Parameter URL, von der die verwundbare Anwendung Informationen holen soll. Die Anwendung wiederum fragt selbst diese URL ab und leitet die Antwort (unter Umständen aufbereitet) an den Benutzer weiter. Ein Angreifer kann über geänderte URLs in dem Parameter versuchen Informationen von anderen Diensten/Servern zu bekommen, die nicht für Benutzer der Anwendung bestimmt sind. So können auch Informationen von Servern abgefragt werden, die für den normalen Benutzer nicht erreichbar sind, weil diese evtl. in einem internen Netzwerk stehen.
Der zweite Server ist eigentlich von außen nicht zu erreichen und da die Anfrage dann von dem Server mit der verwundbaren Anwendung kommt, hilft auch keine Firewall. Über diesen Weg können z.B. auch die Metadaten von Cloudanbietern abgefragt werden, in denen dann unter Umständen Token und/oder Passwörter zu finden sind. Die Anfragen sind nicht auf das HTTP-Protokoll beschränkt. Die verwundbare Anwendung könnte auch andere Protokolle wie file:// nutzen. Neben der direkten Übergabe von URLs in Formularparametern oder Query-Parametern können weitere Wege zu einer Server Side Request Forgery führen. Ein solcher Weg den Server dazu zu bewegen andere Dienste zu kontaktieren ist über XML External Entities (XEE). Das kann passieren, wenn die Anwendung dem Benutzer erlaubt XML-Dateien hochzuladen. XML-Dateien haben grundsätzlich die Möglichkeit eigene Entities zu definieren:
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE code [ <!ELEMENT cmd ANY> <!ENTITY file_test SYSTEM "file:///etc/shadow"> <!ENTITY honey SYSTEM "http://honeypot.perl-services.de"> ]>
Auf die dann später im Dokument zugegriffen werden kann:
<greeting>Hello WINGS</greeting>
<cmd>&file_test;</cmd>
<request_url>&honey;</request_url>
Bei der Entity &file_test; wird über das file:// -Protokoll auf eine Datei des Servers zugegriffen. Wenn der Inhalt des XML dem Benutzer angezeigt wird, gelangen so sensitive Daten zu dem Angreifer.
Durch das Verwenden der Entity &honey; wird der Zugriff auf die URL ausgelöst. Mit etwas mehr Aufwand schafft man es auch, den Inhalt der Datei an die URL zu schicken.
Mögliche Auswirkungen
Je nach Ausprägung der Schwachstelle, können Unbefugte darüber an Informationen gelangen. Welche Informationen das sind, hängt auch davon ab, welche Informationen von dem zuletzt abgefragten Server preisgegeben werden.
Hat der Benutzer die Möglichkeit, Dateien per URL auf dem Server abzulegen, könnte das auch zu Remote Code Execution führen.
Weitere Auswirkungen können sein:
- XML-Attacken
- XSS
- Denial of Service
Vorbeugung
Um sich vor Server Side Request Forgery zu schützen, können Allow und Deny Listen angelegt werden. Mit der Allow -Liste werden URLs/IPs festgelegt, die vom Benutzer genutzt werden dürfen. Alle anderen URLs/IPs werden abgelehnt.
Mit Deny-Listen werden nur bestimmte URLs/IPs (z.B. die Hostnamen und IP-Adressen der Server im internen Netzwerk) von der Verwendung ausgeschlossen. Alle anderen URLs/IPs können vom Benutzer genutzt werden. Diese beiden Möglichkeiten haben den Nachteil, dass es viele Möglichkeiten gibt, wie Angreifer diese Einschränkungen umgehen. Z.B. über das "Maskieren" von URLs oder dass es Alternative Darstellungen gibt (localhost → 127.0.0.1, ::, ::1), die von der Anwendung nicht erkannt werden. Oder bei den erlaubten URLs/IPs eine Anwendung mit einem Open Redirect zu finden. Dann kann dem Server erstmal diese URL mitgegeben werden, die übergebene Anwendung antwortet mit einem Redirect der wieder eine URL enthält, die eigentlich nicht genutzt werden kann.
Die beste Möglichkeit, sich vor der SSRF-Lücke zu schützen ist es, dem Benutzer erst gar keine Möglichkeit einzuräumen, URLs zu übergeben.
Parsen von URLs ist nicht trivial
Allow/Deny-Listen zur Vorbeugung der Schwachstelle haben einen großen Nachteil: Es muss die Benutzereingabe geprüft werden. Dazu wird in der Regel die URL geparst und z.B. der Hostname und/oder Port geprüft. Unterschiedliche Bibliotheken verhalten sich aber unterschiedlich.
Sprache / Bibliothek | URL | -- |
---|---|---|
-- | http://foo@test:13@google.com | http://127.0.0.1:11211:80 |
Python/ urllib | Host: google.com | Host: 127.0.0.1, Port: "Value Error" |
Python / urllib3 | Host: google.com | Fehler beim Parsen! |
Perl / Mojo::URL | Host: test:13@google.com | Host: 127.0.0.1:11211, Port: 80 |
Perl / URI | Host: google.com | Host: 127.0.0.1:11211, Port: 80 |
Perl / http::Tiny | Host: test:13@google.com | Host: 127.0.0.1:11211, Port: 80 |