Der ein oder andere hat vieleicht schon man von XSRF gehört haben.
Heute gehts mal darum, was XSRF genau ist, warum es auftriff und wie man dieses Sicherheitsproblem umgehen kann.
Es handelt sich dabei - grob gesagt - um den ungewollten aufruf einer URL oder das ungewollte senden an eine URL per POST.
Nehmen wir also als Beispiel einmal die URL http://www.example.net/wp-login.php?action=logout, die den aktuell angemeldeten User ausloggen würde. Statt der Logout-Url ist es natürlich auch möglich eine URL zu verwenden, die weitaus schlimmere Dinge anstellt wie einen User lösche, einen neuen anlegen o.Ä..
Die Gefahren liegen auf der Hand: Wird die URL direkt aufgerufen wird die (un)gewünschte Aktion ausgeführt.
Der Angreifer muss es also nur schaffen, das diese URL irgendwie aufgerufen wird.
Dies kann natürlich über viele verschiedene Arten.
Beispielsweise kann die URL als Bild auf einer beliebigen Webseite eingebunden werden.
Der Browser versucht nun auf die Datei zuzugreifen. Dabei wird natürlich - in diesem Fall - der Logout ausgeführt.
Besonders sind in diesem Falle Forensysteme, Gästebuche, etc. betroffen, in denen es möglich ist, auch externe Bilder über den [img]-BBCode einzubinden. Denn da muss der Benutzer nicht einmal eine andere Webseite besuchen.
Auch das Aufrufen über CSS oder ein verstecktes Iframe ist natürlich möglich. Genauso wie das Einbinden eines Formulars auf einer beliebigen Seite mit der Logout-Url als Ziel, mit dessen Hilfe dann dann ein Request ausgelöst wird. (Ggf. kann sogar der Submit automatisch über Javascript erledigt werden.)
Im Extremfall ist ein XSRF auch über eine XSS-Lücke möglich. Dann hilft auch ein Token nicht mehr (siehe unten). Den der kann einfach mittels Javascript ausgelesen werden und bietet demnach auch keinen Schutz mehr. (Also immer schön Usereingaben prüfen! ;))
Problemlösungen
Auch hier gibt es wieder ein paar Ansätze. Viele davon versprechen Sicherheit, die bei genauerer Betrachtung allerdings nur begrenzt wirksam sind.
Statt GET einfach POST zu verwenden macht zwar das Ausnutzen schwieriger, aber Möglichkeiten gibt es dann immer noch genug!
Das Bug-Tracking-System Mantis beispielsweise erfordert bei Aktionen im Adminbereich alle x Minuten die erneute Eingabe von Benutzernamen und Passwort. Allerdings lassen sich ohne Erneuten Login auch Bugs bearbeiten oder löschen. Auch für den Admin-Bereich besteht so weiterhin ein Restrisiko.
Eine wirksame Möglichkeit wäre bei allen wichtigen Funktionen ein Captcha einzubauen und damit auch das mehrfache Abschicken zu verhindern. Aber man kann sich vorstellen, dass das weder besonders barrierefrei, noch schön für den User ist. Damit fällt diese - zumindest meiner Meinung nach - auch flach.
Bleibt also die letze Möglichkeit:
Tokens. Dabei wird ein Code generiert, der in URLs oder Formulare eingebunden wird, die kritische Befehle ausführen. Stimmen der Code nicht mit dem gespeicherten überein, wird eine Fehlermeldung ausgegeben und der Befehl einfach nicht ausgeführt.
Problem dabei ist nun: Macht der User einen neuen Tab auf und öffnen ein neues Formular wird der Token überschrieben und das alte Formular funktioniert nicht mehr.
Die Lösung wäre also: Pro Formular ein Token anzulegen, welches mit der einer eindeutigen ID gekoppelt ist. (z.B. Threadid, Forumid, …)
Die Speicherung kann z.B. bei PHP im $_SESSION-Array erfolgen.
Ich werde wohl die nächsten Wochen eine passende PHP-Klasse schreiben, die sich um die Generierung, Speicherung und um den Check kümmert. Die findet ihr dann natürlich auch hier.

