Is an X-Requested-With header server check sufficient to protect against a CSRF for an ajax-driven application? Is an X-Requested-With header server check sufficient to protect against a CSRF for an ajax-driven application? ajax ajax

Is an X-Requested-With header server check sufficient to protect against a CSRF for an ajax-driven application?


I'd say it's enough. If cross-domain requests were permitted, you'd be doomed anyway because the attacker could use Javascript to fetch the CSRF token and use it in the forged request.

A static token is not a great idea. The token should be generated at least once per session.

EDIT2 Mike is not right after all, sorry. I hadn't read the page I linked to properly. It says:

A simple cross-site request is one that: [...] Does not set custom headers with the HTTP Request (such as X-Modified, etc.)

Therefore, if you set X-Requested-With, the request has to be pre-flown, and unless you respond to pre-flight OPTIONS request authorizing the cross-site request, it won't get through.

EDIT Mike is right, as of Firefox 3.5, cross-site XMLHttpRequests are permitted. Consequently, you also have to check if the Origin header, when it exists, matches your site.

if (array_key_exists('HTTP_ORIGIN', $_SERVER)) {    if (preg_match('#^https?://myserver.com$#', $_SERVER['HTTP_ORIGIN'])        doStuff();}elseif (array_key_exists('HTTP_X_REQUESTED_WITH', $_SERVER) &&        (strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'))    doStuff(); 


I do not believe that this is safe. The same origin policies are designed to prevent the documents from different domains from accessing the content that is returned from a different domain. This is why XSRF problems exist in the first place. In general XSRF doesn't care about the response. It is used to execute a specific type of request, like a delete action. In the simplest form, this can be done with a properly formatted img tag. Your proposed solution would prevent this simplest form, but doesn't protect someone from using the XMLHttp object to make the request.You need to use the standard prevention techniques for XSRF. I like to generate a random number in javascript and add it to the cookie and a form variable. This makes sure that the code can also write cookies for that domain. If you want more information please see this entry.

Also, to pre-empt the comments about XMLHttp not working in script. I used the following code with firefox 3.5 to make a request to google from html running in the localhost domain. The content will not be returned, but using firebug, you can see that the request is made.

<script>var xmlhttp = false; if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {    try {        xmlhttp = new XMLHttpRequest();    } catch (e) {        xmlhttp = false;    }}if (!xmlhttp && window.createRequest) {    try {        xmlhttp = window.createRequest();    } catch (e) {        xmlhttp = false;    }}xmlhttp.open("GET", "http://www.google.com", true);xmlhttp.onreadystatechange = function() {    if (xmlhttp.readyState == 4) {        alert("Got Response");        alert(xmlhttp.responseText)    }}xmlhttp.send(null)alert("test Complete");


I do not think this offers any kind of protection. An attacking site could still use xmlhttprequest for its cross-site request bypass your check.