Angriffe auf Webanwendungen – Teil 4: CSRF

Vorherige Teile der Serie

CSRF steht für Cross-Site Request Forgery und läuft komplett beim Opfer ab. Das einzige, was der Angreifer tut, ist dem Opfer einen speziellen Link zuzuschicken. GMail war mal anfällig für CSRF-Attacken. Dass klar wird, was sich genau dahinter verbirgt, gibts erstmal ein Beispiel.

Beispielangriff

Das Opfer ist bei facebook eingeloggt – was man ja sowieso als facebook-User quasi immer ist, auch wenn man nicht auf der Seite selbst unterwegs ist. Jetzt schickt der Angreifer dem Opfer einen durch einen URL-Shortener verschlüsselten Link zu, der aber in echt

http://www.facebook.com?deleteAccount=1

lautet und – zack, der Account ist futsch. Ist natürlich quatsch, die Jungs von facebook haben sich da schon Gedanken zu gemacht. Aber das Prinzip ist wohl klargeworden. Man kann sogar als Angreifer noch einen Schritt weitergehen und auf einer Webseite ein Bild einbinden, welches einen speziellen Link referenziert. Beispiel:

<img src="http://www.gmail.com?to=chef@firma.de&subject=Kündigung&text=Ich%20kündige!!!" />

„Kritische“ Anfragen nur per $_POST zuzulassen ist auch keine Lösung, denn ein Angreifer könnte in einem iframe einfach einen POST-Request in einer Form ausführen, der dann etwa wie folgt aussieht

<form action="http://www.facebook.com/profile.php" method="post">
	<input name="deleteAccount" value="1" />
	<input type="submit" />
</form>
<script>
	document.forms[0].submit();
</script>

Auch ein Referrer-Check ist nicht zu empfehlen, weil damit evtl. Leute hinter Proxies ausgeschlossen werden. Außerdem könnte man per CURL den Referrer ja auch bequem faken.

Abwehrtechniken

So wirklich hilfreich ist eigentlich nur ein sogenanntes Shared-Secret bei gleichzeitiger, absoluter „XSS-Freiheit“ einer Webseite. Dazu gleich mehr. Wir erzeugen einen beliebigen, zufälligen String (=shared secret) und stecken ihn in die Session:

<?php
$sharedsecret = md5(uniqid());
$_SESSION['sharedsecret'] = $sharedsecret;
?>

Weiterhin wird dieses Shared Secret in ein Hidden-Feld in der eigentlichen Form gesetzt:

<form action="validate.php" method="POST">
	... some fields...
	<input type="hidden" name="sharedsecret" value="<?php echo $sharedsecret; ?>" />
	... some fields...
</form>

In der aufgerufenen validate.php wird nun gecheckt, ob das per $_POST übertragene Shared Secret gleich dem der Session ist. Ist dem nicht so, wurde eine CSRF-Attacke erkannt. Wie oben bereits erwähnt ist die Voraussetzung zum funktionieren dieser Technik eine absolute XSS-Freiheit der Webseite, denn wenn der Angreifer per eingeschleustem Javascript Zugriff auf die Seite hat, kann er auch das Hidden-Feld auslesen und gelangt auf diese Art und Weise dann doch wieder an das Shared Secret.

Update: Ich habe einen neuen Artikel veröffentlicht, der sich mit kreativen „Einsatzmöglichkeiten“ von CSRF befasst.

Update 2: Ich habe (mit Dank an Oliver aus den Kommentaren) ein sinnvolleres (weil funktionierendes) Beispiel gewählt.

Weitere Posts:

Dieser Beitrag wurde unter php, Security, webdev veröffentlicht. Setze ein Lesezeichen auf den Permalink.

6 Antworten auf Angriffe auf Webanwendungen – Teil 4: CSRF

  1. Oliver sagt:

    “Kritische” Anfragen nur per $_POST zuzulassen ist auch keine Lösung, denn ein Angreifer könnte in einem iframe einfach einen POST-Request ausführen, …

    Das ist zwar richtig, aber Dein Beispiel ist falsch. Mit CURL über PHP sendet Dein Server die Anfrage. :-)

    1. david sagt:

      Da ist mir in meinem Leichtsinn was entgangen, danke für die Klarstellung. Habs im Post entsprechend verbessert.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert