Possible security issue using request.read()

112 views
Skip to first unread message

Andriy Sokolovskiy (coldmind)

unread,
Apr 5, 2015, 1:50:27 PM4/5/15
to django-d...@googlegroups.com
(I discussed this issue before with Florian Apolloner in secu...@djangoproject.com, and we decided to open a thread here).

Consider simple view:


class MyView(View):
     
def patch(self, request, *args, **kwargs):
         request
.read()
         
return HttpResponse('test')

Next, consider request:

curl -X PATCH http://localhost:8000/my-view/ -H 'Content-Length: 4' --data "test"


It will return 'test', as expected.
But, with the next request,


 curl
-X PATCH http://localhost:8000/my-view/ -H 'Content-Length: 5' --data "test"

when Content-Length is greater that actual data, it will stuck at
https://github.com/django/django/blob/5bc3123479bd97dc9d8a36fa9a3421a71063d1da/django/core/handlers/wsgi.py#L41

`stream.read()` is calling method from python's stdlib socket -
`socket.read()`.
And inside it is stucking at `data = self._sock.recv(left)`.

For example, django-rest-framework is calling `request.read()` in it's parsers,
and this lib is popular, so every POST or PATCH request may cause this
issue.

Without proper frontend server configuration, server may become vulnerable to some DoS-attacks.
This can be resolved with setting some timeout  - https://gist.github.com/coldmind/a45879b0e4941336b24e.
But, I'm not sure that this is the right way to resolve it.

At least, this issue should be documented, but I believe that there is a way to resolve it in code,
without hoping that frontend server will deal with it.

Florian Apolloner

unread,
Apr 5, 2015, 4:37:59 PM4/5/15
to django-d...@googlegroups.com
Technically we'd set the sockettimeout already in the __init__ of LimitedStream, but in the end I think this is better fixed at the loadbalancer/webserver level as with any other attack similar/equal to "slowloris". There speaks nothing against docs though…

Cheers,
Florian
Reply all
Reply to author
Forward
0 new messages