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)

csrf_middleware_ajax.diff (528 bytes ) - added by xlax 16 years ago.
csrf_check_ajax_requests_too.diff (890 bytes ) - added by Jeroen Pulles <jeroen.pulles@…> 16 years ago.
Get the CSRF token from HTTP headers when using Ajax requests
csrf_middleware_ajax_flash_patch.diff (824 bytes ) - added by herrstagl 16 years ago.
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)

Download all attachments as: .zip

Change History (22)

comment:1 by xlax, 16 years ago

Component: UncategorizedContrib apps
Keywords: CSRF AJAX added

comment:2 by simon, 16 years ago

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.

comment:3 by xlax, 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 xlax, 16 years ago

Attachment: csrf_middleware_ajax.diff added

comment:4 by xlax, 16 years ago

Edit
I have attached the diff file, I hope it is as wanted...

comment:5 by xlax, 16 years ago

Has patch: set
Needs tests: set

comment:6 by Eric Holscher, 16 years ago

Triage Stage: UnreviewedDesign decision needed

comment:7 by Jeroen Pulles <jeroen.pulles@…>, 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 Jeroen Pulles <jeroen.pulles@…>, 16 years ago

Get the CSRF token from HTTP headers when using Ajax requests

comment:8 by anonymous, 16 years ago

Cc: jeroen.pulles@… added

comment:9 by Jeroen Pulles <jeroen.pulles@…>, 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 Jeroen Pulles <jeroen.pulles@…>, 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 xlax, 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 John Millikin, 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?

[1] http://www.securityfocus.com/archive/1/441014

comment:13 by herrstagl, 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 herrstagl, 16 years ago

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 Carl Meyer, 16 years ago

Cc: carl@… added

comment:15 by DerCorny, 16 years ago

Cc: stefan.cornelius@… 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 LI Daobing, 16 years ago

Cc: lidaobing@… added

comment:17 by jojo, 16 years ago

Cc: johannes.beigel@… added

comment:18 by neithere, 16 years ago

Cc: neithere@… added

comment:19 by Bob Thomas, 16 years ago

Resolution: fixed
Status: newclosed

This was fixed in [9554]

Note: See TracTickets for help on using tickets.
Back to Top