tgext.routes changes

Søren Løvborg sorenl at unity3d.com
Thu Apr 14 13:17:42 UTC 2016


Sorry, this is going to get long. :-)

Thomas De Schampheleire wrote:
> So this means updating Kallithea. Do you happen to be interested and
> available for such change?

Yes. I am currently looking into the Kallithea code to see how this
would work. There is definitely room for improvement. I'll get back to
you (and the list) when I have something more concrete.

Next, I wrote:
>>> (Aside: I did not look at the tgext.routes code, but I assume the
>>> override support is opt-in? Enabling it automatically for all applications
>>> could cause security issues for applications that don't have CSRF
>>> protection.)

Alessandro Molina replied:
> Nope, there is no opt-in.
> There isn't in routes itself too:
> https://github.com/bbangert/routes/blob/master/routes/middleware.py#L61-L70
>
> Also even though you would opt-out you can still perform CSRF in any case by
> using an XMLHTTPRequest or a form.

Well, in Routes, it's an opt-out, but the option is there (the
use_method_override argument). I think it's a mistake to enable by
default.

Messing around with the HTTP request like this is definitely not
something you should do in a library, unless the application
explicitly asks for it, and even then only under certain limited
circumstances. This is why:

Per the HTTP standard, GET, POST and PUT/DELETE belong to three
different classes of HTTP methods, with different operational
semantics. Changing one for another has implications not only on a web
application level, but throughout the HTTP stack.

First of all, per the HTTP standard, a GET request must be free of
side effects. Using a method override to turn a GET request into e.g.
a POST request at the application layer can cause a host of issues,
since it violates assumptions held by the rest of the stack (that
includes WSGI middleware, HTTP servers, HTTP accelerators, HTTP
proxies and the browser itself). Therefore, you should never allow a
GET method to be overridden, and I frankly consider it a bug that
Routes (and now tgext.routes) does this.

Similarly, PUT and DELETE are required to be idempotent, that is,
sending the request multiple times should have the same effect as
sending it once. Turning e.g. a PUT into a POST could violate this
rule, but is fortunately not supported by Routes nor tgext.routes.

Now, taking a POST request and turning it into a GET, PUT or DELETE
request, is acceptable under the HTTP standard, because there are no
restrictions on side-effects or idempotence for POST requests.
However, it can poke holes (albeit tiny holes) in the fragile security
sandbox of HTML/JavaScript, because the modern browser security model
treats GET/POST differently from PUT/DELETE, in that a HTML form can
only send GET/POST requests, while you need XMLHttpRequest to send PUT
or DELETE requests, and XMLHttpRequest is subject to stricter
same-origin rules than a HTML form. (Which is why CSRF-attacks are
traditionally implemented using an auto-submitting HTML form, not an
XMLHttpRequest.)

These same-origin rules are rather spotty, and even browser vendor and
version dependent, which is why all serious web apps have CSRF
protection. But the fact that the security protections are weak is
still a poor argument for poking more holes in them. Hence method
overrides should be something the application specifically enables,
once it has proper CSRF protection in place. Even then, method
overrides must only be possible for POST requests, not GET/PUT/DELETE
(or any other).

Best,
Søren


More information about the kallithea-general mailing list