Cross-Site Request Forgery

In diesem Blogpost berichte ich über Cross-Site Request Forgery. 

Was ist CSRF?

Cross-Site Request Forgery ist eine Web-Sicherheitslücke, die sehr alt und bekannt ist und deshalb unbedingt verhindert werden muss. CSRF ist auch als XSRF, “Sea Surf”, Session Riding, Cross-Site Reference Forgery und Hostile Linking bekannt. CSRF beschreibt eine Attacke, wenn ein Angreifer den Browser eines authentifizierten Benutzer täuscht, um ungewollt bösartige Aktionen auf einer Website auszuführen. Es werden grundsätzlich bösartige Anfragen von einem authentifizierten Benutzer an eine Webanwendung gesendet. Die Auswirkung eines CSRF Angriffes können je nach Berechtigung des Benutzers begrenzt sein. Die Response (Antwort) auf die Request (Anfrage) kann der Angreifer nicht sehen. Daher konzentrieren sich CSRF-Angriffe auf Zustandsänderungen und nicht auf den Diebstahl von Daten. 

CSRF erschien im Jahre 2013 in der Liste der Top-10-Sicherheitsrisiken für Webanwendungen des Open Web Application Security Project (OWASP) auf, wurde aber in der Version von 2017 gestrichen.

Wie genau wird ein CSRF-Angriff ausgeführt?

Um einen CSRF-Angriff auszuführen, müssen zwei Dinge geschehen: 

  • Ein authentifizierter Benutzer wird von dem Angreifer dazu gebracht, auf einen Link zu klicken oder eine Seite zu laden. Dies kann unter anderem durch Social Engineering wie bei einem Phishing-Angriff erreicht werden. Wenn die Seite aufgerufen wird (durch Link-klick),  wird das vom Angreifer eingefügte Skript ausgeführt. 
  • Der Angreifer sendet eine HTTP-Request vom Browser des Benutzers. Die Website verarbeitet die Request, ohne zu unterscheiden, ob die Request vom richtigen Benutzer oder dem Angreifer gesendet wurde.

Wie kann man sich vor CSRF-Angriffen schützen?

Selbst wenn Non-GET-Requests beschränkt sind, sind sie nicht vollständig geschützt. Es können immer noch POST-Requests von Scripts und Seiten, die auf andere Domänen gehostet werden, an die Seite gesendet werden. Damit man sicher ist, dass nur gültige HTTP-Requests angenommen werden, muss jede HTTP-Response ein secret und unique (geheimes und eindeutiges) Token haben, was der Server verifizieren muss.

Das nennt man Anti-Forgery Token. Jedes mal, wenn der Server eine Seite rendert (vor allem wenn es sensible Aktionen ausführt), sollte er ein Anti-Forgery Token in ein verstecktes HTML-Formularfeld schreiben. Der Server validiert dann das Token, und alle Aufrufe mit fehlenden oder ungültigen Token werden zurückgewiesen.

Anti-Forgery Tokens sind typischerweise zufällige Zahlen, die in einem Cookie oder auf dem Server gespeichert werden. Der Server vergleicht das an die eingehende Request angehängte Token mit dem im Cookie gespeicherten Wert. Wenn die Werte identisch sind, akzeptiert der Server die gültige HTTP-Anfrage.

Anti-Forgery Token in ASP.NET Core

In ASP.NET Core werden die Tokens automatisch zu den Formularen hinzugefügt, wenn man z.B. die asp-* Tags verwende:

<form asp-controller="User" asp-action="Create" method="post">
   <!-- Form details -->
</form>

Durch diese Tags wird in wirklichkeit folgendes erzeugt:

<form method="post" action="/User/Create">
  <!-- Form details -->
  <input name="__RequestVerificationToken" type="hidden" value="CfDJ8NrAkSldwD9CpLR...LongValueHere!" />
</form>

Dies ist aber nur ein Teil der Anforderung, um sich vor CSRF-Angriffe zu schützen. Man muss auch überprüfen, ob die Tokens serverseitig gültig ist. Das geht auch sehr einfach, denn es existiert ein Attribut namens “[ValidateAntiForgeryToken]”. Dieses Attribut gibt man den Aktionen im Controller mit (genau wie z.B. [HttpPost] oder [HttpGet]), damit es auch etwas bewirkt. 

public class UserController
{
  [HttpPost]
  [ValidateAntiForgeryToken]
  public IActionResult Create()
  {
    // ...
    return View();
  }
}