【问题标题】:Validating Uploaded Files in Django在 Django 中验证上传的文件
【发布时间】:2010-12-17 06:34:57
【问题描述】:

一个Django应用程序,我的工作具有Event模型。一个Event可以具有相关联的照片,静态HTML文件和PDF文件。 P>

我想允许受信任的用户上传这些文件,但我警惕的安全性,尤其是在看过下面in the Django docs(链接)。 P>

请注意,每当你处理 上传的文件,你应该密切 注意的地方,你上传 他们和什么类型的他们的文件, 为了避免安全漏洞。验证所有 上传文件,以便你确定 文件是什么,你认为他们是。为了 举例来说,如果一味让别人 上传文件,而无需验证,到 目录中的Web内的 服务器的文档根目录,然后有人 可以上传一个CGI或者PHP脚本和 通过访问执行该脚本的 网址在您的网站。不允许。 P>

我如何可以验证不同类型的文件?我很想听听处理这种事情,或者进一步阅读的链接的任何人的经验。我有一种感觉:HTML文件可能是太冒险了,在这种情况下,我会加以限制上传权限的管理员。 P>

【问题讨论】:

    标签: python django security file-upload


    【解决方案1】:

    所有答案都集中在验证文件上。这几乎是不可能的。

    Django 开发人员不会要求您验证文件是否可以作为 cgi 文件执行。他们只是告诉你不要把他们放在他们处决的地方。

    你应该把所有 Django 的东西放在一个专门的 Django 目录中。该 Django 代码目录不应包含静态内容。 不要将用户文件放在 Django 源代码库中。

    如果您使用的是 Apache2,请查看基本 cgi 教程:http://httpd.apache.org/docs/2.0/howto/cgi.html

    Apache2 可能设置为运行ScriptAlias 文件夹中的任何文件。 不要将用户文件放在/cgi-bin//usr/local/apache2/cgi-bin/ 文件夹中。

    Apache2 可能设置为服务器 cgi 文件,具体取决于 AddHandler cgi-script 设置。 不要让用户提交带有.cgi.pl 等扩展名的文件。

    但是,您确实需要清理用户提交的文件,以便它们可以安全地在其他客户的计算机上运行提交的 HTML 对其他用户不安全。它不会损害您的服务器。您的服务器只会将其吐回给任何请求它的人。获取 HTML 清理程序。

    另外,SVG 可能不安全。它过去有错误。 SVG 是一个包含 javascript 的 XML 文档,因此它可能是恶意的。

    PDF 是……棘手的。您可以将其转换为图像(如果您确实需要),或提供图像预览(并让用户自行承担下载风险),但这对于尝试使用它的人来说会很痛苦。

    考虑一个正常文件的白名单。嵌入在 gif、jpeg 或 png 文件中的病毒看起来就像一张损坏的图片(或无法显示)。如果您想偏执,请使用 PIL 将它们全部转换为标准格式(嘿,您还可以检查尺寸)。净化的 HTML 应该没问题(去掉脚本标签不是火箭科学)。如果清理过程很糟糕(或者你只是小心翼翼),我猜你可以把它放在一个单独的服务器上。

    【讨论】:

    • 使用单独的域是最安全的。这样一来,如果有人走私了一个同时作为图像内容和脚本内容的文件,它就没有同源权限。
    【解决方案2】:

    对于图像,您也许可以只使用Python Imaging Library (PIL)。

    Image.open(filepath)
    

    如果文件不是图片,则会抛出异常。我对 Python/Django 很陌生,所以其他人可能有更好的方法来验证图像。

    【讨论】:

    • django.forms 包含一个自动为您进行验证的 ImageField。
    【解决方案3】:

    您要对上传的内容做的第一件事是将其存储在一个不能直接下载的目录中。如果您的应用存在于 ~/www/ 中,请考虑将您的数据放入 '~/data/`。

    第二件事,你需要确定用户上传了什么样的文件,然后为每个文件类型创建规则。

    您不能信任基于扩展名的文件,因此请使用 Fileinfo 之类的名称。然后为每个 mime 类型创建一个验证器。 ImageMagick 可以验证图像文件。为了获得更高的安全性,您可能必须对 pdf 和 flash 文件等文件运行病毒扫描程序。对于 html,您可能需要考虑限制为标签的子集。

    我找不到与 Fileinfo 模块等效的 Python,但始终可以执行 /usr/bin/file -i。大多数允许上传的系统会创建一个内容名称或 ID。然后他们使用 mod_rewrite 解析 URL,并在磁盘上查找内容。一旦找到内容,它就会使用 sendfile 或类似的东西返回给用户。例如,在内容被批准之前,可能只有上传的用户才能查看。

    【讨论】:

    • 感谢您的回复。我正在使用 Django,所以最好我想要 Fileinfo 和 ImageMagick 的 Python 等价物。关于将内容存储在私人目录中的好建议,直到我认为它是安全的。
    • python-magic 是 unix 的 Python 实现 file 命令:github.com/ahupp/python-magic
    【解决方案4】:

    这有点特定于您的托管环境,但这是我所做的:

    使用 Nginx 而不是 apache 提供所有用户上传的内容,并将其全部作为静态内容提供(即使用户上传它也不会运行任何 php 或 cgi)

    【讨论】:

    • 感谢您的回复。我很想知道如何使用 lighttpd 获得类似的结果。
    • 大多数 Web 服务器都能够提供静态文件。请参阅 lighttpd 文档,了解如何为此设置目录。
    【解决方案5】:

    您可以使用 BeautifulSoup 验证 html 文件

    【讨论】:

    • 我知道美丽的汤,但堆栈溢出的以下答案表明它不会捕获所有 XSS 攻击 - stackoverflow.com/questions/699468/…
    • 如果你想捕获 XSS - 你可以在 BeautifulSoup 制作的 html 上尝试 Genshi sanitizer
    • 一个有效的上传可能不是有效的html
    【解决方案6】:

    “受信任的用户”是一个主观术语。是您亲自认识的人,还是仅在您的应用上创建帐户的人?不要让不认识的人访问您的文件系统。

    让某人能够上传文件在任何情况下都有点危险,我认为应该避免这种情况。上周我在自动上传 html 代码时遇到了类似的问题,我决定将其存储在数据库中。我认为在大多数情况下,您可以使用数据库而不是文件系统。

    验证的一个问题是您必须为任何类型的文件编写一个新的验证器。这可能是未来的一个限制,在某些情况下是一项艰巨的任务。

    所以,我建议重新考虑基于数据库的设计。

    【讨论】:

    • 我知道“受信任的用户”并相信他们不会上传恶意内容。危险在于我是否可以相信他们不会让他们的密码落入坏人之手。
    • 密码窃取是另一个问题。 django salted hash 应该有帮助,但我们永远不知道。这是不授予文件系统访问权限的另一个论据。
    • @luc 这是一个荒谬的答案。除非该网站是静态网站,否则用户将始终必须上传某种文件,例如个人资料图片。但如果网站是某种文件内容管理平台,那么大多数时候用户肯定会上传文件,因为这符合网站的目的。相反,您可以放置​​文件验证器。
    猜你喜欢
    • 2019-05-13
    • 1970-01-01
    • 2012-07-29
    • 2013-12-14
    • 2012-11-15
    • 2011-06-29
    • 2016-03-02
    • 2019-02-25
    • 2017-12-08
    相关资源
    最近更新 更多