Skip navigation to main content

OWASP : Cross-Site Request Forgery (CSRF)

This is the eighth in a series of posts on the OWASP Top Ten.

As the name possibly suggests this risk is the not-so-distant cousin of the Cross-Site Scripting (XSS) risk we saw earlier in this series.

It still requires the attacker finding some freetext that will go unsanitised into the body of the target website but, in contrast to XSS, it is not attempting to leak data out to some other 3rd-party URL or IP address, or use JavaScript hosted elsewhere to execute on our victims browser.

Instead it makes the assumption that the user is logged authenticated with the web server somehow. The attacker then uses injected HTML or JavaScript to execute a legitimate command (or sequence of commands) that using that users privilege on the site.

Let's see how that works in practice

Back at our fictitious "Plunger Corp", let's say we have a privileged API which credits a customer with a refund. This can only be used by a suitably authorised user, and targets another user's account to initiate the fund transfer. An example API call looks like this:

http://acmeplunger.com/transfer.php?toAcct=<target>&amount=<total to send>

The transfer.php script checks the privileges of the user making the call by using session cookies, so we know the call is authorised…!?

Just supposing our naughty hacker finds out about the API call, but recognises that even though they have an account with acmeplunger.com and is able to log in, the script checks for valid Function Level Access Rights, and so they can't call the API.

But the site (as they've already discovered) is vulnerable to a XSS vulnerability, and so they can insert HTML into product reviews. So they inject the following HTML:

This plunger is ok, but I'm not sure the colour matches my eyes <img src="http://acmeplunger.com/transfer.php?toAcct=nastyHacker&amount=1999" height="0" width="0" /> Please have a customer rep contact me. Thank you.

So the hacker has inserted some HTML that makes a call to an API that only an elevated or privileged user can call. So this will have no effect if browsed by an unauthenticated user or another user with a normal account. But when a customer rep looks at this product page with the review on it, it will trigger a call to the API, and invisibly transfer spondooliks into the hackers back pocket.

So I just patch XSS, and I'm done for CSRF as well.

This is a somewhat contrived example, but there are many APIs out there that use this form, and they are all vulnerable to this attack unless they do additional checks to ensure the call is authorised.

What makes this even less trivial to fix is that it needn't be an exploit of a XSS vulnerability on our webserver that our attacker uses. The suspect HTML could be injected on to another site (e.g. acmelampshades.com), but assumes you're logged into the acmeplungers.com (remember those session cookies?), and can therefore make those CSRF API calls back to the vulnerable script.

How annoying!

Add a confirmation screen? A motivated hacker will write evil javascript to run through a several step process to achieve a particular result, so can manage a series of calls to multiple APIs/pages.

It's not just about cash either; those calls might elevate his account to administrator rights, change the users password to lock them out or any number of other functions. As you can see this type of attack can be quite disastrous if left unchecked.

One defence against this attack is to add a hidden 'token' to the body of the API call. This way a check can be made against the session variables that it matches that token, and in our example (given that our attacker is only sending GET variables) we'd notice the attack, and can manage it.

Additionally having interactive UI controls, such as Captcha, requires interaction with the webserver that is not easy circumvented via javascript or the like, adding additional protection to our API call.

Next time : Using Components with Known Vulnerabilities

Join the conversation on Twitter @OWASP   #OWASPtop10   #CSRF