söndag 12 december 2010

CSRF via POST

Jag håller på att förbereda mig för en presentation på OWASP IBWAS'10 i veckan. En av sakerna jag tänkt visa är CSRF mot POST-metoder och det sessionslösa CSRF-skyddet "double submit".

CSRF
CSRF (cross-site request forgery) innebär att en attacksajt som lurar till sig icke ont anande surfare gör anrop in till en annan sajt och därigenom utnyttjar att offrets webbläsare automatiskt lägger till sessions-/autentiseringskakor i request:et. Det blir alltså ett legitimt anrop till servern utan att offret vet eller ser något.

CSRF mot GET
Normalt snackas det ju om CSRF mot GET-metoder. Dessa kan göras med enkla img-taggar, typ:

<img src="http://www.google.com/search?q=OWASP" border="0" height="0" width="0" />

Den taggen på attacksajten kommer alltså att göra en Google-sökning på "OWASP" med offrets Google-identitet och inget syns. Skälet till att detta fungerar är att bilder får hämtas cross-domain och att webbläsaren inte har en aning om att den URL:en inte kommer returnera en bild.

Men de flesta känsliga requesten är POST (eller PUT/DELETE i dessa REST-tider) och kan alltså inte anropas med en img-tagg. En riktig formulär-POST skickar ju dessutom inparametrar i request-kroppen och kan därför inte ha dem uppradade på URL:en som i fallet ovan med ?q=OWASP.

CSRF mot POST
Kan man då göra CSRF mot POST-metoder? Japp. Tänk er en URL owasp.org/ws/oneliners som tar emot enradskommentarer av användare autentiserade till owasp.org. Då skulle attacksajten kunna innehålla följande formulär:

<form id="target" method="POST" action="https://owasp.org/ws/oneliners" style="visibility:hidden">
<input type="text" value="I hate OWASP!" name="oneLiner"/>
<input type="submit" value="Go" />
</form>

... och sen har följande JavaScript, i det här fallet byggt på JQuery:

<script type="text/javascript">
$(document).ready(function() {
$('#target').submit();
});
</script>

... vilket innebär att så fort ett offer surfar in på attacksajten så postar han/hon "I hate OWASP!" till one liners-URL:en.

POST-CSRF mot Twitter?
Går denna attack att genomföra mot stora kommersiella tjänster? Ja, det har gått men tjänsteleverantörerna har lärt sig och implementerat skydd, ofta det så kallade double submit-skyddet.

Ett CSRF-formulär som twittrar åt offret skulle se ut så här:

<form id="target" method="POST" action="https://twitter.com/status/update" style="visibility:hidden">
<input type="text" value="74691c4d14f2c70d0936e2478fb09f68d532282" name="authenticity_token"/>
<input type="text" value="This was sent via POST CSRF" name="status"/>
<input type="text" value="true" name="twttr"/>
<input type="text" value="true" name="return_rendered_status"/>
<input type="text" value="" name="lat"/>
<input type="text" value="" name="lon"/>
<input type="text" value="" name="place_id"/>
<input type="text" value="false" name="display_coordinates"/>
<input type="submit" value="Go" />
</form>

Som ni ser så finns det en intressant parameter authenticity_token. Utan att ha avkodat Twitters alla cookies så förmodar jag att det är ett double submit-skydd. För varje request till Twitter-sidan så skickas en kaka med ett slumpgenererat värde med. För att en POST ska godkännas så ska denna kaka ha samma värde som POST-parametern authenticity_token. Eftersom attacksidan aldrig kan läsa offrets Twitter-kakor innan requestet så kan den heller inte inkludera en korrekt authenticity_token. Svaret från Twitter blir:

403 Forbidden: The server understood the request, but is refusing to fulfill it.

Inga kommentarer: