I am soliciting advice on correctly implementing nonces for ajax powered forms.
The forms are written in plain html.
The way, I have currently implemented is - the default form submit is intercepted through javascript and before processing the form, a get call is made to get a nonce token in JSON, the resulting nonce data is appended to the form data and is sent to the server for further processing via POST (XHR).
For security reasons, I have limited the scope of the nonce to 300 seconds. And the url that generates nonce values check for http referer to ensure that requests are made from the site. However, this may be futile due to the reasons mentioned in Referer header: privacy and security concerns (MDN)
Thank you.
I am having a hard time making CSRF Guard to work on Ajax Requests in my Grails Application. I already added the Javascript Servlet in the page and followed instructions in their website. The problem is that it kept on saying that I have missing token. Aside from that, our Ajax request is not inside a form which I would assume that CSRF would look for forms and auto-inject the token for Ajax POST requests. I just merely get each parameters and pass it as data in my Ajax POST request.
You should try with the pattern outlined by the author of this question Grails - Is there a recommended way of dealing with CSRF attacks in AJAX forms?
It seems creating and handling anti-CSRF tokens for Ajax calls in an Angular application is non-trivial and some are getting around the problem by applying a single token to every Ajax call. For example here.
The solution is quite neat. We just generate the token on the server and send it along with the first loaded page after sign-in. Then we ensure it goes out with all future requests like this:
$http.defaults.headers.common['RequestVerificationToken'] = 'token should go here';
But I am concerned this may simplify the job of an attacker. They need only get hold of $http in order to make any valid request. Is this the case? Is this method safe? Is there a 'best practice' regarding Ajax requests and CSRF?
Angular automatically does this for you.
Read Cross Site Request Forgery (XSRF) Protection section.
DOCS
I also suggest you read up CSRF, and what it is, if malicious script is already in your page it does not need to do cross-site requests to pose as the victim.
According to this article it is enough to validate X-Requested-With header for AJAX requests sent by jQuery. So in this case it is not necessary to implement tokens?
And if yes, where is defined that cross-browser requests are not allowed?
Thanks in advance.
The article itself says that this method is insufficient:
Warning
The method of preventing CSRF attacks described in this post
is now considered to be insufficient. A comment on this post links to
more details about an attack that circumvents it.
Django comes with CSRF protection middleware, which generates a unique per-session token for use in forms. It scans all incoming POST requests for the correct token, and rejects the request if the token is missing or invalid.
I'd like to use AJAX for some POST requests, but said requests don't have the CSRF token availabnle. The pages have no <form> elements to hook into and I'd rather not muddy up the markup inserting the token as a hidden value. I figure a good way to do this is to expose a vew like /get-csrf-token/ to return the user's token, relying on browser's cross-site scripting rules to prevent hostile sites from requesting it.
Is this a good idea? Are there better ways to protect against CSRF attacks while still allowing AJAX requests?
UPDATE: The below was true, and should be true if all browsers and plugins were properly implemented. Unfortunately, we now know that they aren't, and that certain combinations of browser plugins and redirects can allow an attacker to provide arbitrary headers on a cross-domain request. Unfortunately, this means that even AJAX requests with the "X-Requested-With: XMLHttpRequest" header must now be CSRF-protected. As a result, Django no longer exempts Ajax requests from CSRF protection.
Original Answer
It's worth mentioning that protecting AJAX requests from CSRF is unnecessary, since browsers do not allow cross-site AJAX requests. In fact, the Django CSRF middleware now automatically exempts AJAX requests from CSRF token scanning.
This is only valid if you are actually checking the X-Requested-With header server-side for the "XMLHttpRequest" value (which Django does), and only exempting real AJAX requests from CSRF scanning.
If you know you're going to need the CSRF token for AJAX requests, you can always embed it in the HTML somewhere; then you can find it through Javascript by traversing the DOM. This way, you'll still have access to the token, but you're not exposing it via an API.
To put it another way: do it through Django's templates -- not through the URL dispatcher. It's much more secure this way.
Cancel that, I was wrong. (See comments.) You can prevent the exploit by ensuring your JSON follows the spec: Always make sure you return an object literal as the top-level object. (I can't guarantee there won't be further exploits. Imagine a browser providing access to the failed code in its window.onerror events!)
You can't rely on cross-site-scripting rules to keep AJAX responses private. For example, if you return the CSRF token as JSON, a malicious site could redefine the String or Array constructor and request the resource.
bigmattyh is correct: You need to embed the token somewhere in the markup. Alternatively, you could reject any POSTs that do have a referer that doesn't match. That way, only people with overzealous software firewalls will be vulnerable to CSRF.