Opened 16 years ago
Closed 16 years ago
#8127 closed (fixed)
CSRF + AJAX
Reported by: | xlax | Owned by: | nobody |
---|---|---|---|
Component: | Contrib apps | Version: | dev |
Severity: | Keywords: | CSRF AJAX | |
Cc: | jeroen.pulles@…, carl@…, stefan.cornelius@…, lidaobing@…, johannes.beigel@…, neithere@… | Triage Stage: | Design decision needed |
Has patch: | yes | Needs documentation: | no |
Needs tests: | yes | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
I've got a patch ready for anyone who needs it (if it's accepted) to use CSRF with AJAX.
It's simply adding a line to the main CSRF function, stating that if AJAX is being used, there's no need for a check.
I know of no issues regarding this. I can submit the file immediatelly. (It's been tested here)
Attachments (3)
Change History (22)
comment:1 by , 16 years ago
Component: | Uncategorized → Contrib apps |
---|---|
Keywords: | CSRF AJAX added |
comment:2 by , 16 years ago
comment:3 by , 16 years ago
It's using the request.is_ajax() function. This is documented here: http://www.djangoproject.com/documentation/request_response/#methods
Quote:
"""
Returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'.
"""
I'm currently trying to do the svn diff. First time I did it, so please don't shoot me if I did something wrong :)
by , 16 years ago
Attachment: | csrf_middleware_ajax.diff added |
---|
comment:5 by , 16 years ago
Has patch: | set |
---|---|
Needs tests: | set |
comment:6 by , 16 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
comment:7 by , 16 years ago
Hi,
Actually, this is a problem that might bite the unwary: If you use the CSRF middleware, and do JSON posts, you will run into trouble right now.
Personally, I prefer to check the key in JSON request bodies as well (being a bit paranoid, hey I'm using the CSRF middleware :-/).
So the attached diff (csrf_check_ajax_requests_too.diff) checks for a HTTP_X_CSRFMIDDLEWARETOKEN
in the HTTP header. You can easily add that header in most Ajax libraries, e.g. request.setHeader('X-CsrfMiddlewareToken', document.getElementById('csrfmiddlewaretoken').value);
.
The only downside you have is that there might not be a key on a webpage because it has no <form method="post">
in the response. That seems to be the exception in my experience, and that can be worked around just as easy.
by , 16 years ago
Attachment: | csrf_check_ajax_requests_too.diff added |
---|
Get the CSRF token from HTTP headers when using Ajax requests
comment:8 by , 16 years ago
Cc: | added |
---|
comment:9 by , 16 years ago
Uh, oops:
My patch should have checked the Content-Type of the request body, and assume that requests of the type application/x-www-form-urlencoded
are still handled with the existing request.POST['csrfmiddlewaretoken']
.
comment:10 by , 16 years ago
More rationale:
Actually, this is a problem that might bite the unwary: If you use the CSRF middleware, and do JSON posts, you will run into trouble right now.
That goes for any POST request that isn't application/x-www-form-urlencoded. Which is why it would be welcome to make the request processing more robust, regardless of the design choice to check for the token or not.
comment:11 by , 16 years ago
Perhaps the best way to go is to make CSRF generate a key per-standard, and make it available. That way, at all points in the application, the string is usable and the ajax user could implement that into the "form" sent through.
comment:12 by , 16 years ago
I found a SecurityFocus article[1] that mentions that Adobe Flash is capable of both cross-site requests and setting arbitrary HTTP headers. If this is true, then relying on the X-Requested-With header will allow hostile cross-site requests if a user visits a malicious site.
Is this concern accurate, or does Flash enforce the same cross-site rules as the XMLHttpRequest object?
comment:13 by , 16 years ago
We had some issues with csrf and ajax when we used an flash uploader in combination with windows and firefox. in this special case, flash is sending the IE cookies instead of the Firefox cookies and therefore CSRF raises an error because no valid session is available. What we did, to get csrf working even with the flash YUI upload:
- we added the csrfmiddlewaretoken to the ajax post request
- we wrote a patch during the implementation of www.xipax.com for the middleware.py which checks if there is POST variable called session_id, if not, it falls back to the standard behaviour of the CSRF middleware
This file is attached to the ticket
by , 16 years ago
Attachment: | csrf_middleware_ajax_flash_patch.diff added |
---|
patch which allows to provide a session id within a post request: userfull for flash based uploaders where authentication is required (done for www.xipax.com)
comment:14 by , 16 years ago
Cc: | added |
---|
comment:15 by , 16 years ago
Cc: | added |
---|
Being post-1.0 now, how is it going with the design descision? There are also related bugs, e.g. #6709 and #7167. The patches here actually look kind of good to me and I don't think that the SafeForms discussed in #7167 will help for highly dynamic AJAX, so why not extend the CSRF middleware with these patches and add a nice and simple template tag to generate the token?
While this might not be the best solution ever, I'm still convinced that a lot of people will benefit from a "standard" solution to at least mitigate the problem in an easy way - the patches don't mess up too much and I think it's way better than having users develop their own hackish and potentially insecure method of extending the CSRF protection. Think of all the snippets and apps out there that are currently lacking a standard way of tackling this problem (e.g. threaded-comments, iirc).
comment:16 by , 16 years ago
Cc: | added |
---|
comment:17 by , 16 years ago
Cc: | added |
---|
comment:18 by , 16 years ago
Cc: | added |
---|
Assuming this is a check for the X-Requested-By: XMLHttpRequest header, I'm all for it - it's a nice, secure way of allowing Ajax requests to avoid having to include a form token, which can be tricky to make available to the Ajax code otherwise.