1
我使用以下代码在django应用程序中从登录受保护的视图中提供上传的文件。使用django提供服务文件 - 这是一个安全漏洞
您是否认为此代码中存在安全漏洞?我有点担心用户可能会在上传/之后在url中放置任意字符串,并将其直接映射到本地文件系统。
其实我不认为这是一个漏洞问题,因为对文件系统的访问仅限于使用UPLOAD_LOCATION设置定义的文件夹中的文件。
UPLOAD_LOCATION = is set to a not publicly available folder on the webserver
url(r'^upload/(?P<file_url>[/,.,\s,_,\-,\w]+)', 'project_name.views.serve_upload_files', name='project_detail'),
@login_required
def serve_upload_files(request, file_url):
import os.path
import mimetypes
mimetypes.init()
try:
file_path = settings.UPLOAD_LOCATION + '/' + file_url
fsock = open(file_path,"r")
file_name = os.path.basename(file_path)
file_size = os.path.getsize(file_path)
print "file size is: " + str(file_size)
mime_type_guess = mimetypes.guess_type(file_name)
if mime_type_guess is not None:
response = HttpResponse(fsock, mimetype=mime_type_guess[0])
response['Content-Disposition'] = 'attachment; filename=' + file_name
#response.write(file)
except IOError:
response = HttpResponseNotFound()
return response
编辑:根据伊格纳西奥巴斯克斯 - 艾布拉姆斯评论更新来源:
import os.path
import mimetypes
@login_required
def serve_upload_files(request, file_url):
mimetypes.init()
try:
file_path = os.path.join(settings.UPLOAD_LOCATION, file_url)
#collapse possibly available up-level references
file_path = os.path.normpath(file_path)
#check if file path still begins with settings.UPLOAD_LOCATION, otherwise the user tampered around with up-level references in the url
#for example this input: http://127.0.0.1:8000/upload/..\test_upload.txt results having the user access to a folder one-level higher than the upload folder
#AND check if the common_prefix ends with a dir separator, Because although '/foo/barbaz' starts with '/foo/bar'
common_prefix = os.path.commonprefix([settings.UPLOAD_LOCATION, file_path])
if common_prefix == settings.UPLOAD_LOCATION and common_prefix.endswith(os.sep):
fsock = open(file_path,"r")
file_name = os.path.basename(file_path)
mime_type_guess = mimetypes.guess_type(file_name)
if mime_type_guess is not None:
response = HttpResponse(fsock, mimetype=mime_type_guess[0])
response['Content-Disposition'] = 'attachment; filename=' + file_name
else:
response = HttpResponseNotFound()
else:
print "wrong directory"
response = HttpResponseNotFound()
except IOError:
response = HttpResponseNotFound()
return response
谢谢,我会尝试这些提示,并将粘贴新代码在我的问题。为什么是Nr。 4重要? – 2010-03-31 07:56:02
因为虽然'/ foo/barbaz'以'/ foo/bar'开头,但它不在它之下。 – 2010-03-31 08:09:22
我重新编写了源代码。现在看起来很省钱。你怎么看? – 2010-03-31 09:02:51