Django ImageField验证(是否足够)?

Django ImageField验证(是否足够)?,django,security,file-upload,django-models,Django,Security,File Upload,Django Models,我有很多用户上传的内容,我想验证上传的图像文件实际上不是恶意脚本。在Django文档中,它指出ImageField: 从FileField继承所有属性和方法,但也验证上载的对象是否为有效图像 这完全正确吗?我读过压缩或以其他方式操作图像文件是一个很好的验证测试。我假设PIL会做这样的事情 ImageField对我的图像上传安全性有很大帮助吗?另一个测试是使用该命令。它检查文件中是否存在“幻数”,以确定其类型。在我的系统上,文件包包括libmagic以及基于ctypes的包装/usr/lib64/

我有很多用户上传的内容,我想验证上传的图像文件实际上不是恶意脚本。在Django文档中,它指出ImageField:

从FileField继承所有属性和方法,但也验证上载的对象是否为有效图像

这完全正确吗?我读过压缩或以其他方式操作图像文件是一个很好的验证测试。我假设PIL会做这样的事情

ImageField对我的图像上传安全性有很大帮助吗?

另一个测试是使用该命令。它检查文件中是否存在“幻数”,以确定其类型。在我的系统上,
文件
包包括
libmagic
以及基于ctypes的包装
/usr/lib64/python2.7/site packages/magic.py
。看起来您使用它的方式如下:

import magic

ms = magic.open(magic.MAGIC_NONE)
ms.load()
type =  ms.file("/path/to/some/file")
print type

f = file("/path/to/some/file", "r")
buffer = f.read(4096)
f.close()

type = ms.buffer(buffer)
print type

ms.close()
(代码来自。)


至于你最初的问题:“卢克,读一下来源。”

django/core/files/images.py:

"""
Utility functions for handling images.

Requires PIL, as you might imagine.
"""

from django.core.files import File

class ImageFile(File):
    """
    A mixin for use alongside django.core.files.base.File, which provides
    additional features for dealing with images.
    """
    def _get_width(self):
        return self._get_image_dimensions()[0]
    width = property(_get_width)

    def _get_height(self):
        return self._get_image_dimensions()[1]
    height = property(_get_height)

    def _get_image_dimensions(self):
        if not hasattr(self, '_dimensions_cache'):
            close = self.closed
            self.open()
            self._dimensions_cache = get_image_dimensions(self, close=close)
        return self._dimensions_cache

def get_image_dimensions(file_or_path, close=False):
    """
    Returns the (width, height) of an image, given an open file or a path.  Set
    'close' to True to close the file at the end if it is initially in an open
    state.
    """
    # Try to import PIL in either of the two ways it can end up installed.
    try:
        from PIL import ImageFile as PILImageFile
    except ImportError:
        import ImageFile as PILImageFile

    p = PILImageFile.Parser()
    if hasattr(file_or_path, 'read'):
        file = file_or_path
        file_pos = file.tell()
        file.seek(0)
    else:
        file = open(file_or_path, 'rb')
        close = True
    try:
        while 1:
            data = file.read(1024)
            if not data:
                break
            p.feed(data)
            if p.image:
                return p.image.size
        return None
    finally:
        if close:
            file.close()
        else:
            file.seek(file_pos)

看起来它只是一次读取1024字节的文件,直到PIL说它是一个映像,然后停止。这显然不会检查整个文件的完整性,因此这实际上取决于您所说的“保护我的图像上载安全”的含义:非法数据可能会附加到图像并通过您的站点传递。有人可以通过上传大量垃圾或非常大的文件来破坏你的网站。如果不检查任何上载的标题或对图像上载的文件名进行假设,则可能容易受到注入攻击。等等。

Django使用PIL验证通过表单上传的图像。 看

PIL文档说明了以下关于verify()的内容:

尝试确定文件是否已损坏,而不进行实际解码 图像数据。如果这种方法发现任何问题,它会提出适当的建议 例外情况。此方法仅适用于新打开的图像;如果 图像已加载,结果未定义。还有,如果你 如果使用此方法后需要加载图像,则必须重新打开 图像文件


您还应该注意,ImageField仅在使用表单上载时才进行验证。如果您自己保存模型(例如,使用某种下载脚本),则不会执行验证。

Hi Mike,我可以看出这在哪里很方便,但与ImageField结合使用时是否冗余?很明显,ImageField执行某种类型的文件类型验证感谢您的更新,关于限制您是对的。我考虑了一些防止大文件上传的策略。注射攻击的可能性是我最大的担忧。
try:
    # load() is the only method that can spot a truncated JPEG,
    #  but it cannot be called sanely after verify()
    trial_image = Image.open(file)
    trial_image.load()

    # Since we're about to use the file again we have to reset the
    # file object if possible.
    if hasattr(file, 'reset'):
        file.reset()

    # verify() is the only method that can spot a corrupt PNG,
    #  but it must be called immediately after the constructor
    trial_image = Image.open(file)
    trial_image.verify()
 ...
 except Exception: # Python Imaging Library doesn't recognize it as an image
    raise ValidationError(self.error_messages['invalid_image'])