For example, if you know that i am logged in to our blog admin backend most of the time, and you know its url and software, you could trick me into visiting a special prepared url. That url contains a small javascript that automatically submits a fake form to our admin backend, and short time later everybody is surprised to read on our blog that Mayflower will leave the domain of web application development and open a butcher’s shop instead.
Since the authors of our blog software are smart people, they implemented a CSRF protection. And not only them, even we not as smart PHProjekt developers implemented one.
There are three popular ways to protect your software against CSRF:
- using POST instead of GET
The non working but popular counter measure. It helps against requests hidden in image tags, but it won’t for requests forged by javascript. - a hidden one time key / token in every form This is what we – and a lot of other people, too – did. Every form gets a token, and only if this token exists the form is accepted. The remote javascript can’t know the token, so it can’t submit a valid form
- referrer-check
Another neat way to protect against CSRF, if there is no strange browser or proxy configuration that prevents the referrer header involved.
If the origin of a submission is from a different domain, don’t trust it.
Whether you implemented a, b or c – if you got an XSS on your site, your protection does not help anymore. XSS allows you to inject javascript into the target hosts javascript sandbox. This allows you to submit XmlHttpRequest (XHR) calls to the target server.
- XHR, as well as javascript DOM injections, can be used to submit a post form
- The token can be circumvented by a XHR request that reads the original form page and extracts the token form variable
- XmlHttpRequest.setRequestHeader(‘Referer’, ‘http://targetdomain.com/spoofedreferer.php’) allows you to set a fake header.
Conclusion:
If you want to secure your application against CSRF, make sure that there are no XSS on your site, too.