Skip to content
Browse files

BACKWARDS-INCOMPATIBLE: Fix XSRF security vulnerability.

This is a backwards-incompatible change.  Applications that previously
relied on a blanket exception for XMLHTTPRequest may need to be modified
to explicitly include the XSRF token when making ajax requests.

The tornado chat demo application demonstrates one way of adding this
token (specifically the function postJSON in demos/chat/static/chat.js).

More information about this change and its justification can be found at
http://www.djangoproject.com/weblog/2011/feb/08/security/
http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails

Closes #214.
  • Loading branch information...
1 parent 2338348 commit 90b8078739c8166d26de723178fb2151043e8218 @bdarnell bdarnell committed Feb 8, 2011
Showing with 18 additions and 7 deletions.
  1. +18 −7 tornado/web.py
View
25 tornado/web.py
@@ -709,16 +709,27 @@ def xsrf_token(self):
def check_xsrf_cookie(self):
"""Verifies that the '_xsrf' cookie matches the '_xsrf' argument.
- To prevent cross-site request forgery, we set an '_xsrf' cookie
- and include the same '_xsrf' value as an argument with all POST
- requests. If the two do not match, we reject the form submission
- as a potential forgery.
+ To prevent cross-site request forgery, we set an '_xsrf'
+ cookie and include the same value as a non-cookie
+ field with all POST requests. If the two do not match, we
+ reject the form submission as a potential forgery.
+
+ The _xsrf value may be set as either a form field named _xsrf
+ or in a custom HTTP header named X-XSRFToken or X-CSRFToken
+ (the latter is accepted for compatibility with Django).
See http://en.wikipedia.org/wiki/Cross-site_request_forgery
+
+ Prior to release 1.1.1, this check was ignored if the HTTP header
+ "X-Requested-With: XMLHTTPRequest" was present. This exception
+ has been shown to be insecure and has been removed. For more
+ information please see
+ http://www.djangoproject.com/weblog/2011/feb/08/security/
+ http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby-on-rails
"""
- if self.request.headers.get("X-Requested-With") == "XMLHttpRequest":
- return
- token = self.get_argument("_xsrf", None)
+ token = (self.get_argument("_xsrf", None) or
+ self.request.headers.get("X-Xsrftoken") or
+ self.request.headers.get("X-Csrftoken"))
if not token:
raise HTTPError(403, "'_xsrf' argument missing from POST")
if self.xsrf_token != token:

0 comments on commit 90b8078

Please sign in to comment.
Something went wrong with that request. Please try again.