Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is exposing a session's CSRF-protection token safe?

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?

like image 945
John Millikin Avatar asked Sep 27 '08 23:09

John Millikin


People also ask

How safe is CSRF token?

A CSRF token is a secure random token (e.g., synchronizer token or challenge token) that is used to prevent CSRF attacks. The token needs to be unique per user session and should be of large random value to make it difficult to guess. A CSRF secure application assigns a unique CSRF token for every user session.

Should CSRF token be hidden?

For additional safety, the field containing the CSRF token should be placed as early as possible within the HTML document, ideally before any non-hidden input fields and before any locations where user-controllable data is embedded within the HTML.

When should you use CSRF protection?

19.3 When to use CSRF protection When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.

Why CSRF tokens should not be transmitted using cookies?

CSRF tokens prevent CSRF because without token, attacker cannot create a valid requests to the backend server. CSRF tokens should not be transmitted using cookies. The CSRF token can be added through hidden fields, headers, and can be used with forms, and AJAX calls.


2 Answers

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.

like image 153
Carl Meyer Avatar answered Sep 27 '22 20:09

Carl Meyer


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.

like image 36
Matt Howell Avatar answered Sep 27 '22 20:09

Matt Howell