[mod_python] req.sendfile() problem

Graham Dumpleton grahamd at dscpl.com.au
Fri Aug 4 22:51:01 EDT 2006

On 05/08/2006, at 2:42 AM, Jim Gallacher wrote:

> Thomas J. Schirripa wrote:
>> def handler(req):
>> 	fields = util.FieldStorage(req)
>>         #Note: the filename is an absolute path, so I am going to  
>> split that up into directory and filename for clarity
>> 	filename = os.path.basename(fields["filename"])
>> 	path = os.path.dirname(fields["filename"])
>> 	req.headers_out["Content-Disposition"] = "attachment; filename=% 
>> s" % filename
>> 	req.content_type = "text/plain"
>> 	req.sendfile("%s/%s" % (directory, filename))
>> 	return apache.OK
> Also, it goes without saying that the filename provided
> by in the request should not be trusted. Do some checking to ensure it
> is valid value.

What Jim has pointed out can't be overemphasised enough. The way your  
is written I could potentially steal you /etc/passwd file and much more.

What you should at least do is something like the following:

ALLOWED_PREFIX = '/some/path/to/fetchable/files'

def handler(req):

     fullpath = os.path.normpath(fields['filename'])
     if not fullpath.startswith(ALLOWED_PREFIX):
         return apache.HTTP_BAD_REQUEST

The os.path.normpath() eliminates any '.' and '..' directory  
references. You then
check to ensure the path then actually begins with the path prefix  
for where your
files actually live.

Better still, do not use an absolute path, instead only ever send  
back a relative
path. You should still use os.path.normpath() to eliminate '.' and  
'..' references.
Then, you add the relative path to a path prefix which is only  
defined within
your script. In other words, you never send the path prefix back to  
the client.


More information about the Mod_python mailing list