Kristof Dreier — where tech meets text

Willkommen im privaten Blog von Kristof Dreier, Webentwickler und Mac-Enthusiast aus Münster. Thematisch dreht es sich hier um Webdevelopment mit dem Zend Framework, kleinere Einschübe über Cocoa und vielleicht auch mal ein Blick in die Weiten von Ruby on Rails.

CSRF mit Zend_Form unterbinden

Mittwoch, 01. Juli 2009 in

Die Problematik existiert ja im Grunde schon seit Ewigkeiten, das Bewusstsein dafür ist aber noch nicht ganz so alt. Ich bin erst letztens über ein Paper von Stefan Esser wieder drauf aufmerksam gemacht worden. Wem die kryptische Abkürzung im Titel nichts sagt, folgt nun eine kleine kurze Einführung in Cross-Site Request Forgery kurz CSRF.

Was ist Cross-Site Request Forgery?

CSRF-Schwachstellen tun sich auf, wenn auf einer Website ein authentifizierter Benutzer sensitive Aktionen durchführen kann, ohne das vorher geprüft wurde, ob diese Aktion auch tatsächlich von der Person ausging. Um CSRF-Attacken zu verstehen, sollte man wissen, dass Websites typischerweise nicht überprüfen, ob die Anfrage von einem verifizierten Benutzer kam, sondern sie überprüfen, ob der Browser des Benutzer für diese Aktionen authentifiziert war. Da Browser von Natur aus Code ausführen, besteht die Gefahr, dass ein Script beim Aufruf einer Seite einen Request an eine weitere Seite schickt. In dieser zweiten Seite ist der Benutzer angemeldet und ohne, dass er etwas davon mitbekommt, führt das Script im Hintergrund in seinem Namen eine Aktion in der Seite aus.

Weitere Informationen gibt es bei Wikipedia

Was kann man dagegen tun?

Das sicherste ist jedem Request, der Daten ändern kann, eine für den aktuellen Aufruf gültige und zufällige Zeichenkette mitzugeben. Das passiert am besten über ein Hidden-Input-Feld. Gleichzeitig wird dieses Shared-Secret in der Session des Benutzer gespeichert. Wird das Formular nun abgeschickt, werden diese beiden Werte verglichen. Entweder stimmen die Shared-Secrets überein, das heißt, dass die Anfrage ganz normal abgearbeitet wird, oder sie stimmen nicht überein und der Aufruf wird mit einer entsprechenden Mitteilung verworfen. Wichtig ist, dass für jeden Aufruf dieses Shared-Secret neu generiert wird.

Und was hat das mit Zend_Form zu tun?

In Stefan Essers Paper ist mir aufgefallen, dass die Zend_Form-Komponente soetwas von Haus aus mitbringt. Das Form-Element nennt sich ganz einfach Hash oder Zend_Form_Element_Hash.
Das schöne an diesem Element ist, dass es automatisch einen zufällige Hash-Wert generiert und beim Abschicken des Formulars überprüft, ob der übergebene Wert mit dem generierten übereinstimmt. Das heisst für uns, dass wir unserem Formular nur das Element mitgeben müssen und wir automatisch vor CSRF-Attacken geschützt sind.
Dazu gibt es nun mehrere Möglichkeiten. Die einfachste und effektivste ist es, eine eigene Klasse zu erstellen, die von Zend_Form erbt und in der wir den Konstruktor überschreiben. Das kann dann folgendermassen aussehen:

  1. <?php
  2. class My_Form extends Zend_Form
  3. {
  4.     public function __construct()
  5.     {
  6.         parent::__construct();
  7.         $this->addElement('hash', 'csrf_token',
  8.                     array('salt' => get_class($this) . 's3cr3t%Ek@on9!'));
  9.     }
  10. }

Wenn wir nun ein neues Formular erstellen, erhält es automatisch, ohne dass wir uns darum kümmern müssen ein Hidden-Hash-Feld. Falls eure Formulare also noch ungeschützt sein sollten, holt es am besten direkt nach.

Kommentare

Dein Kommentar


Textile-Hilfe