IT Security in Web Anwendungen VII – Cross-Site Request Forgery (CSRF)

Doğan Uçar

In dem siebten Teil der Blogserie „IT Security in Web Anwendungen“ thematisieren wir Cross-Site Request Forgery (kurz: CSRF oder XSRF), ihre Funktionsweise, verschiedene Arten von CSRF und wie Sie sich demgegenüber schützen. Anhand konkreter Beispiele – in der Programmiersprache „Java“ – wollen wir die wichtigsten Punkte im Bezug auf IT-Security im Bezug auf CSRF aufzeigen und Best Practices auflisten.

web app & csrf schutz
Foto: Mika Baumeister/Unsplash

In unserem ersten Post dieser Blogserie sind wir das Thema „Injections“ angegangen und haben gezeigt, wie diese zustandekommen bzw. zu verhindern sind. In dem zweiten Teil der Serie sind wir auf  File Up-/Download und Storage eingegangen und haben allgemeine Sicherheitsrisiken sowie Prävention und Alternativen aufgelistet. In dem dritten Teil thematisieren wir Sessions und Session Hijacking-Attacken sowie einen möglichen Schutz gegen solcher Attacken. Der vierte Teil thematisierte das HTTP(S)-Protokoll im Allgemeinen und ist auf sicherheitsrelevante Aspekte eingegangen. In dem fünften Teil beschäftigten wir uns mit Datenbanken und wie man sicher mit ihnen kommuniziert und in dem sechsten Teil addressierte das Thema „IT-Security in Web-Server“.

Alle Posts dieser Blogserie sind unabhängig voneinander und das Lesen der vorherigen Posts ist keine Voraussetzung. Zu dem besseren Verständnis zu dem Thema „IT-Security“ empfehlen wir jedoch bei Post #1 anzufangen. Da alle vorangegangenen Posts im Web-Umfeld thematisiert werden, ist es empfehlenswert zumindest die Grundkenntnisse zu haben.

In dem kommenden Posts der Blogserie möchten wir uns tiefergehend mit den verschiedenen Bereichen der IT Security beschäftigen. In insgesamt neun Blogposts möchten wir tiefergehend auf verschiedene Szenarien eingehen, mögliche Schutzmechanismen präsentieren und diese – wenn möglich – durch praktische Beispiele demonstrieren. Nach Blogpost #9 werden wir diese Serie und weitere Tipps und Tricks als PDF zur Verfügung stellen. Sie können sich unter dem nachfolgenden Formular zum Newsletter anmelden, um das PDF zu erhalten:

[newsletters_subscribe form=3]

Was sind Cross-Site Request Forgery?

Cross-Site Request Forgery (oder kurz: CSRF/XSRF) ist eine Art von Angriff, bei dem ein Angreifer einen Benutzer dazu bringt, ungewollt eine bestimmte Aktion auf einer Website auszuführen. Dabei wird ausgenutzt, dass viele Websites vertrauliche Aktionen wie das Ändern von Passwörtern oder das Tätigen von Zahlungen zulassen, ohne den Benutzer jedes Mal erneut zu authentifizieren.

Ein CSRF-Angriff beginnt normalerweise mit einer vom Angreifer präparierten Website oder einer E-Mail, die den Benutzer dazu verleitet, auf einen Link zu klicken oder ein Bild anzuklicken. Durch das Klicken auf den Link oder das Bild wird eine Anfrage an die Zielseite gesendet, um eine bestimmte Aktion auszuführen. Da der Benutzer bereits auf der Zielseite angemeldet ist, kann diese Anfrage ohne weitere Überprüfung ausgeführt werden.

Um ein Beispiel in Java zu geben, nehmen wir an, dass ein Angreifer eine CSRF-Anfrage senden möchte, um das Passwort eines Benutzers zu ändern. Hier ist ein Beispiel für eine solche Anfrage:

import java.net.*;
import java.io.*;

public class CSRFExample {
    public static void main(String[] args) {
        try {
            String targetUrl = "https://example.com/change-password";
            String requestBody = "password=newpassword";
            URL url = new URL(targetUrl);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("POST");
            con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            con.setRequestProperty("Content-Length", Integer.toString(requestBody.getBytes().length));
            con.setRequestProperty("Cookie", "sessionid=abc123"); // Benutzer ist bereits angemeldet
            con.setDoOutput(true);
            DataOutputStream out = new DataOutputStream(con.getOutputStream());
            out.writeBytes(requestBody);
            out.flush();
            out.close();
            System.out.println("Request successful.");
        } catch (Exception e) {
            System.out.println("Request failed: " + e.getMessage());
        }
    }
}

Dieses Beispiel sendet eine POST-Anfrage an die URL „https://example.com/change-password“, um das Passwort des Benutzers zu ändern. Der Cookie „sessionid=abc123“ wird mit der Anfrage gesendet, um zu zeigen, dass der Benutzer bereits angemeldet ist. Wenn der Benutzer auf einer präparierten Website ist, könnte diese Anfrage ohne sein Wissen ausgeführt werden.

Um sich gegen CSRF-Angriffe in Java zu schützen, gibt es verschiedene Methoden, wie beispielsweise die Verwendung von CSRF-Tokens oder die Verwendung von Sicherheitsframeworks wie Spring Security. Diese Methoden erfordern jedoch, dass Entwickler und Systemadministratoren sicherstellen, dass ihre Anwendungen gegen diese Angriffe geschützt sind.

Wie funktioniert Cross-Site Request Forgery?

CSRF-Angriffe funktionieren, indem sie das Vertrauen eines Benutzers in eine Website ausnutzen. Dies geschieht normalerweise, indem der Angreifer den Benutzer dazu bringt, eine Aktion auszuführen, die eine Anfrage an die Zielseite sendet. Diese Anfrage enthält normalerweise Informationen über die Aktion, die der Angreifer ausführen möchte, sowie Informationen darüber, wer die Anfrage sendet (d.h. der Benutzer).

Ein wichtiger Aspekt von CSRF-Angriffen ist, dass sie normalerweise nicht direkt auf die Zielseite abzielen, sondern auf eine Website, die dem Benutzer vertrauenswürdig erscheint. Dies kann beispielsweise eine Website sein, auf der der Benutzer häufig angemeldet ist, oder eine Website, die der Benutzer auf andere Weise als vertrauenswürdig empfindet. Der Angreifer kann eine Website präparieren oder einen Link oder ein Bild in eine E-Mail einfügen, die den Benutzer dazu verleitet, auf den Link oder das Bild zu klicken. Sobald der Benutzer auf den Link oder das Bild klickt, wird die Anfrage an die Zielseite gesendet.

Um einen CSRF-Angriff durchzuführen, benötigt der Angreifer normalerweise einige Informationen über die Zielseite und den Benutzer. Dazu gehört oft der Session-Cookie des Benutzers, der Informationen über seine aktuelle Sitzung auf der Zielseite enthält. Wenn der Angreifer den Session-Cookie des Benutzers hat, kann er die Anfrage so erstellen, dass sie als Teil der aktuellen Sitzung des Benutzers auf der Zielseite ausgeführt wird.

Um sich gegen CSRF-Angriffe zu schützen, gibt es verschiedene Maßnahmen, die Website-Entwickler und -Administratoren ergreifen können. Dazu gehört beispielsweise das Verwenden von CSRF-Tokens, die dem Benutzer bei jeder Anfrage einen zufälligen Token zuweisen, der dann bei der Verarbeitung der Anfrage überprüft wird. Auf diese Weise kann sichergestellt werden, dass die Anfrage nur von einem Benutzer stammt, der die aktuelle Sitzung auf der Website gestartet hat. Andere Schutzmaßnahmen können das Verwenden von Sicherheitsframeworks wie Spring Security oder das Einschränken von Aktionen auf bestimmte HTTP-Methoden sein.

Sicherheit durch Open Source

Kennen Sie schon unseren Open Source Passwort Manager Keestash? Wir bieten für Unternehmen, Teams und Endnutzern sicheres Verwalten von Passwörtern. Auf Wunsch hosten wir Keestash für Sie oder Sie installieren Keestash auf Ihre eigene Hardware.
Interesse? Schreiben Sie uns einfach eine E-Mail oder testen Keestash einfach unter app.keestash.com

Welche Arten von Aktionen können bei einem CSRF-Angriff ausgeführt werden?

Es gibt viele Arten von CSRF-Angriffen und die Szenarien sind vielfältig. Eine nicht vollständige Liste an Beispielen könnte sein:

  • Ein Benutzer könnte versehentlich auf einen Link klicken, der eine ungewollte Aktion auf der Website auslöst, wie das Ändern des Passworts oder das Löschen von Kontoinformationen.
  • Ein Angreifer könnte eine Zahlung in Auftrag geben oder eine E-Mail in Ihrem Namen senden.
  • Ein Angreifer könnte versuchen, sich als Sie auszugeben, indem er Ihre Login-Daten stiehlt und dann eine CSRF-Anfrage sendet, um weitere Informationen zu sammeln oder sich Zugriff auf Ihre Konten zu verschaffen.

Wie können Sie sich vor CSRF-Angriffen schützen?

Es gibt verschiedene Maßnahmen, die Sie ergreifen können, um sich vor CSRF-Angriffen zu schützen:

  1. Verwenden Sie CSRF-Tokens: CSRF-Tokens sind zufällige Codes, die in jeder Anfrage gesendet werden und vom Server überprüft werden, um sicherzustellen, dass die Anfrage vom Benutzer stammt, der sie gesendet hat. Wenn ein Angreifer versucht, eine gefälschte Anfrage zu senden, ohne den CSRF-Token zu kennen, wird der Server die Anfrage ablehnen. Jedoch: es ist von kritischer Bedeutung, dass der Token jedes Mal neu generiert und für pro Benutzer/Anfrage eindeutig ist.
  2. Begrenzen Sie den Zugriff auf Cookies: Es ist wichtig, dass der Zugriff auf Cookies eingeschränkt wird, um CSRF-Angriffe zu verhindern. Dazu kann die „HttpOnly“-Einstellung verwendet werden, die Cookies davor schützt, von JavaScript ausgelesen zu werden. Dadurch wird verhindert, dass ein Angreifer den Session-Cookie des Benutzers stiehlt und ihn in einer CSRF-Anfrage verwendet.
  3. Verwenden Sie HTTP-Methoden zu dem vorgesehenen Zweck: Es ist wichtig, dass Sie Ihre HTTP-Methoden richtig verwenden, um sich vor CSRF-Angriffen zu schützen. Verwenden Sie beispielsweise nur POST-Methoden für Anfragen, die Änderungen an der Datenbank oder am Server vornehmen. GET-Anfragen sollten nur verwendet werden, um Daten abzurufen.
  4. Verwenden Sie CORS: Cross-Origin Resource Sharing (CORS) ist eine Technologie, die es Webanwendungen ermöglicht, die Ressourcen von anderen Domänen anzufragen. Durch die Verwendung von CORS können Sie bestimmte Domänen zulassen oder blockieren, die auf Ihre Ressourcen zugreifen können. Dadurch wird verhindert, dass Angreifer Anfragen von anderen Domänen aus senden.
  5. Verwenden Sie Content Security Policy (CSP): Content Security Policy ist eine Sicherheitsrichtlinie, die es ermöglicht, bestimmte Quellen für Ressourcen auf einer Webseite zu definieren. Dadurch können Sie den Zugriff auf bestimmte Ressourcen wie JavaScript-Dateien und Bilder einschränken. Wenn ein Angreifer versucht, eine Anfrage von einer nicht autorisierten Quelle aus zu senden, wird die Anfrage vom Server abgelehnt.
  6. Schulen Sie Benutzer: Es ist wichtig, Benutzer über CSRF-Angriffe aufzuklären und ihnen beizubringen, wie sie verdächtige Anfragen erkennen können. Benutzer sollten aufgefordert werden, Anfragen von Websites zu überprüfen, bevor sie auf Links klicken oder Anfragen senden. Sie sollten auch darauf hingewiesen werden, dass sie sich von E-Mails und Links fernhalten sollten, die verdächtig erscheinen.

Durch die Anwendung dieser Maßnahmen können Sie sich vor CSRF-Angriffen schützen bzw. das Risiko minimieren und Ihre Website sicherer machen. Es ist jedoch wichtig zu beachten, dass keine dieser Maßnahmen allein ausreicht.

Wir wollen jedoch nicht nur im theoretischen Verharren und möchten anhand eines praktischen Beispiels den effektiven Schutz vor CSRF verdeutlichen. Das nachfolgende Beispiel zeigt ein mögliches Angriffs- und Schutzszenario im Falle von CSRF. In dem Beispiel wird versucht, den Benutzer eine Aktion ausführen zu lassen, die er so nicht vorsieht bzw. ihm schadet.

In dem Beispiel kommt Spring Security zum Einsatz, eine beliebte Java-Bibliothek für die Implementierung von Sicherheitsfunktionen in Webanwendungen. Zunächst müssen Sie sicherstellen, dass Spring Security in Ihrem Projekt eingebunden ist. Dann können Sie eine CSRF-Schutzkonfiguration in Ihrer Spring-Security-Konfigurationsklasse hinzufügen.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
 
    @Bean
    public CsrfTokenRepository csrfTokenRepository() {
        CookieCsrfTokenRepository repository = new CookieCsrfTokenRepository();
        repository.setCookieHttpOnly(false);
        return repository;
    }
}

In dieser Konfiguration wird der CSRF-Schutz aktiviert und die CSRF-Tokens werden als Cookies mit der „HttpOnly“-Einstellung verwendet, um JavaScript-Angriffe zu verhindern. Außerdem haben wir eine eigene Methode csrfTokenRepository() hinzugefügt, um das CsrfTokenRepository-Objekt zu erstellen und die „HttpOnly“-Einstellung auf „false“ zu setzen, um das Lesen des Tokens durch JavaScript zu ermöglichen.

Als nächstes müssen wir sicherstellen, dass das CSRF-Token in jeder Anfrage gesendet wird. Dazu fügen wir dem HTML-Formular ein verstecktes Eingabefeld hinzu:

<form action="/example" method="POST">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
    <input type="submit" value="Submit"/>
</form>

Dieses Formular enthält ein verstecktes Eingabefeld mit dem Namen des CSRF-Parameters und dem CSRF-Token als Wert. Wenn das Formular gesendet wird, wird das CSRF-Token zusammen mit den anderen Formulardaten an den Server gesendet.

Schließlich müssen wir sicherstellen, dass der Server das CSRF-Token in jeder Anfrage überprüft. Dazu können wir das CsrfTokenRepository-Objekt verwenden, das wir zuvor erstellt haben:

@PostMapping("/example")
public ResponseEntity<String> examplePost(@RequestBody ExampleRequest request,
                                           CsrfToken csrfToken) {
    if (!csrfTokenRepository.loadToken(request).equals(csrfToken)) {
        return new ResponseEntity<>("CSRF Token invalid", HttpStatus.FORBIDDEN);
    }
 
    // handle request
 
    return new ResponseEntity<>("Request processed successfully", HttpStatus.OK);
}

Das Beispiel verwendet das CsrfTokenRepository-Objekt, um das CSRF-Token aus der Anfrage zu laden und mit dem CSRF-Token zu vergleichen, das als Parameter an die examplePost-Methode übergeben wird. Wenn das Token ungültig ist, wird eine „Forbidden“-Antwort zurückgegeben. Andernfalls wird die Anfrage bearbeitet und eine „OK“-Antwort zurückgegeben.

Dies ist ein grundlegendes Beispiel für die Implementierung von CSRF-Schutz in Java mit Spring Security. Es gibt auch andere Bibliotheken und Frameworks, die CSRF-Schutz unterstützen, und die genauen Details können je nach Implementierung unterschiedlich sein. Es ist jedoch wichtig, sicherzustellen, dass CSRF-Schutz in jeder Webanwendung implementiert wird, um vor dieser Art von Angriffen geschützt zu sein und die Sicherheit der Anwendung und der Benutzerdaten zu gewährleisten.

IT Security mit Ucar Solutions

Wir bieten Ihnen vollumfänglichen System- und Source-Code Audit zum Absichern Ihrer Datenbanken, Server und Anwendungen gegen eine Vielzahl potenzieller Sicherheitsrisiken und weiteren sicherheitsrelevanten Aspekten – darunter auch den Schutz vor Cross-Site Request Forgery-Attacken. Durch automatisierte und manuelle Prozesse helfen wir Ihnen, Ihre sensiblen und geschäftskritischen Informationen zu schützen und die geltenden Gesetze einzuhalten.

Unsere automatisierten Tests beinhalten u.a. Penetrationtests, toolbasierte Codeanalyse und -dokumentation. Darauf aufbauend analysieren wir den Source-Coden persönlich, versuchen die Architektur zu verstehen und mögliche Probleme bzw. Vorschläge in dem Zusammenhang zu identifizieren bzw. unterbreiten.

Des Weiteren agieren wir auch als „Software-as-a-Service“ (kurz SaaS) Vendor und bieten Ihnen verschiedene Teil- oder Vollkomponenten als Software-Service an, welche vollumfänglich, unter Berücksichtigung aller o.g. sicherheitsrelevanten ununterbrochen zur Verfügung stehen. So können Sie sich um Ihre Anwendung kümmern während wir Teilbereiche zur Verfügung stellen.

Nutzen Sie das nachfolgende Kontaktformular und kontaktieren Sie uns heute noch für ein unverbindliches Erstgespräch. Wir freuen uns darauf!