> On 28 August 2010 22:46, Graham Dumpleton <graham.dumpleton@gmail.com> wrote:
>>
>>
>> On Aug 28, 7:58 pm, "david b." <db.pub.m...@gmail.com> wrote:
>>> Ok so I was looking through the code and I saw this (in
>>> django/core/files/uploadhandler.py) :
>>>
>>> FileUploadHandler
>>> ...
>>>
>>> def new_file(self, field_name, file_name, content_type,
>>> content_length, charset=None):
>>> """
>>> Signal that a new file has been started.
>>>
>>> Warning: As with any data from the client, you should not trust
>>> content_length (and sometimes won't even get it).
>>> """
>>>
>>> So the content_length we control right? - Maybe I missed something but
>>> ... I can say I want to upload a small file then upload a file that
>>> triggers an oom condition / use a lot of memory no ? ...
>>>
>>> And then this.
>>>
>>> class MemoryFileUploadHandler(FileUploadHandler):
>>> """
>>> File upload handler to stream uploads into memory (used for small
>>> files).
>>> """
>>>
>>> def handle_raw_input(self, input_data, META, content_length,
>>> boundary, encoding=None):
>>> """
>>> Use the content_length to signal whether or not this handler
>>> should be in use.
>>> """
>>> # Check the content-length header to see if we should
>>> # If the post is too large, we cannot use the Memory handler.
>>> if content_length > settings.FILE_UPLOAD_MAX_MEMORY_SIZE:
>>> self.activated = False
>>> else:
>>> self.activated = True
>>>
>>> def new_file(self, *args, **kwargs):
>>> super(MemoryFileUploadHandler, self).new_file(*args, **kwargs)
>>> if self.activated:
>>> self.file = StringIO()
>>> raise StopFutureHandlers()
>>>
>>> def receive_data_chunk(self, raw_data, start):
>>> """
>>> Add the data to the StringIO file.
>>> """
>>> if self.activated:
>>> self.file.write(raw_data)
>>> else:
>>> return raw_data
>>>
>>> def file_complete(self, file_size):
>>> """
>>> Return a file object if we're activated.
>>> """
>>> if not self.activated:
>>> return
>>>
>>> self.file.seek(0)
>>> return InMemoryUploadedFile(
>>> file = self.file,
>>> field_name = self.field_name,
>>> name = self.file_name,
>>> content_type = self.content_type,
>>> size = file_size,
>>>
>>> There is a regression test for this BUT --> in the test suite there
>>> is # A small file (under the 5M quota)
>>> which is governed by
>>> (django/tests/regressiontests/file_uploads/uploadhandler.py)
>>>
>>> def receive_data_chunk(self, raw_data, start):
>>> self.total_upload += len(raw_data)
>>> if self.total_upload >= self.QUOTA:
>>> raise StopUpload(connection_reset=True)
>>> return raw_data
>>>
>>> So obviously my proposed attack is to simply say "content length is
>>> tiny" and "this file is actually HUGE".
>>> I hope I missed something :) I don't really want this to occur ...
>>
>> A decent web server such as Apache (under mod_wsgi) will stop reading
>> the original content at the content length specified in the request.
>> Thus not possible to force more than content length down to the
>> application level.
>>
>> Graham
>
> The documentation and code in django suggests that this is not the
> case. So lets assume we are not using apache but another httpd of some
> sort - then this problem will be present.
> http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 seems to
> say otherwise from my reading.
Just to clarify this - I meant that the http content length header
item is *not* required - as per
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4 (also see
4.4.2), so I do not believe that apache would do what you said :) -
there is a default limit in a apache of around 2gb for the attackers
file to reach though.
--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.
No comments:
Post a Comment