Wicket und CSRF (deutsch)

Nach einer Diskussion die ich vor Kurzem zum Thema CSRF (Cross Site Request Forgery) hatte möchte ich kurz auf die Möglichkeiten zum Umgang mit diesem Angriff in Wicket eingehen. Tatsächlich handelt es sich hier um einen oft unterschätzten Angriffsvektor der eine Schwäche des Browsers und nicht der eigentlichen Webanwendung ausnutzt.

Der Angriff

Der Ablauf eines CSRF-Angriffs ist schnell erklärt.

  1. Ein Benutzer authentifiziert sich in einer Webanwendung
  2. Eine entsprechende Sitzung wird eröffnet und der Browser erhält ein Cookie
  3. Der Benutzer navigiert, ohne sich abzumelden, auf eine andere Seite (oder öffnet ein weiteres Tab/Browser-Window).
  4. Auf dieser Seite hat unser Angreifer ein entsprechendes JavaScript oder eine verstecktes Frame eingebaut mit dessen Hilfe der Browser dazu veranlasst wird eine URL innerhalb der anderen Webanwendung zu öffnen.
  5. Da das Cookie immer noch gültig ist wird dies automatisch mitgeschickt und der Angreifer hat Zugriff.

Natürlich versuchen Browserhersteller Möglichkeiten für diesen Angriff zu minimieren.

Grundsätzlich sollte man als Webentwickler aber davon ausgehen, dass diese Mechanismen nicht funktionieren.

So manchem (Jemand fühlt sich gleich angesprochen 😉 ) zuerst die Möglichkeit via AJAX und XmlHTTPRequest in den Sinn. Allerdings gibt es hier eine wichtige Beschränkung die meines Wissens in allen Browsern korrekt umgesetzt ist. Ein XmlHTTPRequest kann nur auf den Ursprungsserver abgesetzt werden. Somit sind extern nachgeladene Skripten außen vor. Hat man natürlich eine Cross-Site-Scripting-Schwäche in der Anwendung …

Die Verteidigung

Grundsätzlich ist Wicket, wie jedes andere Webframework, anfällig für diese Angriffe. Allerdings liefert es auch alles was benötigt wird um diesen Angriff deutlich zu erschweren oder ihn sogar unmöglich zu machen.

In Wicket 1.4 gibt es hierfür die CryptedUrlWebRequestCodingStrategy. Mit folgendem Code-Snipplet kann sie in der Application registriert werden.

...
    protected IRequestCycleProcessor newRequestCycleProcessor() {
        return new WebRequestCycleProcessor() {
        protected IRequestCodingStrategy newRequestCodingStrategy() {
        return new CryptedUrlWebRequestCodingStrategy(new WebRequestCodingStrategy());
    }
...
}

Wicket 1.5 bietet die gleiche Funktionalität im CryptoMapper. Der wie folgt registriert wird:

...
    @Override
    public void init() {
        super.init();
        setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));
    }
...

In beiden Fällen wird von un an für jede neu erzeugte Session ein entsprechender Schlüssel erzeugt und in ihr hinterlegt. Im Folgenden wird jede URL, bevor sie ausgeliefert wird, mit diesem verschlüsselt.

Beim Aufruf einer URL in der Anwendung (via AJAX oder dem Klicken eines Links) versucht Wicket diese zu entschlüsseln. Funktioniert dies nicht, was auf alle URLs zutrifft die nicht von Wicket ausgeliefert wurden, wird eine Fehlermeldung erzeugt.

Nachteile

Alles hat seinen Preis, auch der Schutz vor CSRF-Angriffen. Man verliert die Möglichkeit BookmarkablePages zu nutzen. Auch ihre URLs werden entsprechend verschlüsselt. Da der Schlüssel für jede Session neu erzeugt wird sind diese Links spätestens nach dem Ausloggen ungültig.

Durch die Nutzung von PageMounts kann man dieses Problem abmildern da deren URLs immer verfügbar sind.

Auch mag es stören eine Schlüssel pro Session zu erzeugen da dies die Existenz einer Session voraussetzt. Via Application.getSecuritySettings().setCryptFactory() lässt sich hier ein eigenes CryptFactory registrieren welches einen applikationsweiten Schlüssel erzeugt.

Fazit

Trotz der erwähnten Nachteile sehe ich die CryptedUrlWebRequestCodingStrategy als das sicherste und bequemste Mittel zur Abwehr von CSRF-Angriffen. Wer sich Sorgen um die zusätzliche Last durch die Verschlüsselung macht wird hier demnächst noch eine kleine Lastanalyse finden.

Advertisements

About codepitbull
A nerd, a geek, a software developer. Oh, and married ;)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: