Announcing Tornado 1.1.1: Security update, backwards-incompatible

69 views
Skip to first unread message

Ben Darnell

unread,
Feb 9, 2011, 1:59:05 AM2/9/11
to Tornado Mailing List
Tornado 1.1.1 is a BACKWARDS-INCOMPATIBLE security update that fixes an
XSRF vulnerability.  It is available at

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

wataka

unread,
Feb 9, 2011, 7:58:34 AM2/9/11
to Tornado Web Server
Thanks for the update. I have a question though. I have rolled my own
"get_current_user() method in my base handler class, do I have to
explicitly also set my cookies using
self.set_secure_cookie(my_hashed_session_id) to make the counter XSRF
measures work securely?

Thanks



On Feb 9, 7:59 am, Ben Darnell <b...@bendarnell.com> wrote:
> Tornado 1.1.1 is a BACKWARDS-INCOMPATIBLE security update that fixes an
> XSRF vulnerability.  It is available athttp://github.com/downloads/facebook/tornado/tornado-1.1.1.tar.gz
>
> 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 athttp://www.djangoproject.com/weblog/2011/feb/08/security/http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby...

wataka

unread,
Feb 9, 2011, 8:16:16 AM2/9/11
to Tornado Web Server
Another question, from the docs:

"If xsrf_cookies is set, the Tornado web application will set the
_xsrf cookie for all users and reject all POST requests that do not
contain a correct _xsrf value. If you turn this setting on, you need
to instrument all forms that submit via"

Could we expect this to propagate to other HTTP methods like DELETE
and PUT? Are there workarounds?

Thanks

On Feb 9, 7:59 am, Ben Darnell <b...@bendarnell.com> wrote:
> Tornado 1.1.1 is a BACKWARDS-INCOMPATIBLE security update that fixes an
> XSRF vulnerability.  It is available athttp://github.com/downloads/facebook/tornado/tornado-1.1.1.tar.gz
>
> 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 athttp://www.djangoproject.com/weblog/2011/feb/08/security/http://weblog.rubyonrails.org/2011/2/8/csrf-protection-bypass-in-ruby...

Matt Ferguson

unread,
Feb 9, 2011, 8:22:35 AM2/9/11
to python-...@googlegroups.com

That line just needs to be changed to:

if self.request.method in ("POST", "DELETE", "PUT") and \

Gary B

unread,
Feb 9, 2011, 8:50:31 AM2/9/11
to python-...@googlegroups.com
Yeah, the XSRF method test should at least include the methods tested when parsing a form:




Ben Darnell

unread,
Feb 9, 2011, 7:55:37 PM2/9/11
to python-...@googlegroups.com
No, XSRF protection is independent of how you set your cookies.

-Ben

Ben Darnell

unread,
Feb 9, 2011, 7:57:22 PM2/9/11
to python-...@googlegroups.com
Since it's now possible to pass the XSRF token in an HTTP header, it should probably be checked on all non-idempotent requests (i.e. everything but GET and HEAD).  

-Ben

wataka

unread,
Feb 10, 2011, 6:10:36 AM2/10/11
to Tornado Web Server
Thanks Ben and others. I have patched my Tornado installation locally
as Matt suggested above, would this be implemented officially sometime
soon Ben?

if self.request.method in ("POST", "DELETE", "PUT") and \

Thanks

Robert Buchholz

unread,
Feb 10, 2011, 9:18:12 AM2/10/11
to python-...@googlegroups.com
On Thursday 10 February 2011, Ben Darnell wrote:
> Since it's now possible to pass the XSRF token in an HTTP header, it
> should probably be checked on all non-idempotent requests (i.e.
> everything but GET and HEAD).

From what I know, there is no documented way to generate PUT or DELETE
requests across domains (yet). Of course, if you're building your app to
include XSRF tokens in POST requests, you may as well add them to
PUT/DELETE as well. I'm wondering if we wouldn't want it for GET as well
then, the next Flash/plug-in bug may be just around the corner.


Robert

Ben Darnell

unread,
Feb 10, 2011, 1:45:56 PM2/10/11
to python-...@googlegroups.com
XSRF is a write-only attack - the attacker performs a request for its side effects but cannot directly see the result.  Since GETs should not have side effects they don't need XSRF protection.  Additionally, an XSRF token in GET requests can leak out in referrers, etc.

-Ben

Robert Buchholz

unread,
Feb 11, 2011, 4:01:55 AM2/11/11
to python-...@googlegroups.com
Hey Ben,

On Thursday 10 February 2011, Ben Darnell wrote:
> XSRF is a write-only attack - the attacker performs a request for its
> side effects but cannot directly see the result.

Generally, that is what one would expect. Unfortunately, there were
quite a few bugs in the past (some of them still unfixed) that would
allow an attacker to disclose data by reading the result of a GET
request from another domain in a browser.

> Since GETs should
> not have side effects they don't need XSRF protection.
> Additionally, an XSRF token in GET requests can leak out in
> referrers, etc.

True for general browsing, but if you generate XMLHttpRequests against
some api anyway, adding a header solves this problem.

Robert

Ben Darnell

unread,
Feb 11, 2011, 4:13:36 AM2/11/11
to python-...@googlegroups.com
On Fri, Feb 11, 2011 at 1:01 AM, Robert Buchholz <robert....@agilosoftware.com> wrote:
Hey Ben,

On Thursday 10 February 2011, Ben Darnell wrote:
> XSRF is a write-only attack - the attacker performs a request for its
> side effects but cannot directly see the result.

Generally, that is what one would expect. Unfortunately, there were
quite a few bugs in the past (some of them still unfixed) that would
allow an attacker to disclose data by reading the result of a GET
request from another domain in a browser.


But if the attacker can perform a GET and read the result, they would be able to get the XSRF token.  If cross-domain GETs (with the user's cookies) are possible then the entire web security model kind of falls apart.

-Ben

Robert Buchholz

unread,
Feb 11, 2011, 5:24:56 AM2/11/11
to python-...@googlegroups.com
On Friday 11 February 2011, Ben Darnell wrote:
> But if the attacker can perform a GET and read the result, they would
> be able to get the XSRF token.

That's true, but depending on the specific use case, there may be ways
to secure this. With rich browser apps, the server could hand out a
single session token as a response to an authentication request. That
way we're basically doing cookies without the browser including it
automatically.

> If cross-domain GETs (with the
> user's cookies) are possible then the entire web security model kind
> of falls apart.

Depending on the vulnerability, only certain data types can be read. We
were able to write a three line JavaScript that extends the Object
prototype and then adds a script tag to "execute" JSON from another
domain, collecting the objects that are returned. This worked in certain
versions of chromium and chrome release.

My point is not that these aren't vulnerabilities in the browsers (they
are), so it is fair to say a web application should not have to protect
against it. But if we're building defense in depth (by having PUT and
DELETE XSRF protected when there aren't vulnerabilities yet that would
allow exploitation), as a service developer I want to try to defend
against common vulnerabilities. I see this is not generally possible,
but specific to the web application, its API and workflow.


Robert

Reply all
Reply to author
Forward
0 new messages