Django 和 SuspiciousFileOperation:检测到路径遍历尝试

Posted

技术标签:

【中文标题】Django 和 SuspiciousFileOperation:检测到路径遍历尝试【英文标题】:Django and SuspiciousFileOperation:Detected path traversal attempt 【发布时间】:2021-12-13 03:26:49 【问题描述】:

只有在部署时我才发现自己处于一种奇怪的情况 (debug == false): 我的模型抛出 path traversal attempt 异常。我想为每个上传的文件创建一个目录,并将文件保存在示例中使用的目录 (some.zip) 中。在我的开发环境中,我没有任何问题,一切正常。

models.py:

class Template(models.Model):
    def get_folder(self, filename):
        filename_PATH = Path(filename)
        template_dir = filename_PATH.stem
        return Path(settings.TEMPLATES_FOLDER).joinpath(template_dir, filename)

    name = models.CharField("template", max_length=32, unique=True)
    file = models.FileField("templatefile", upload_to=get_folder, null=True, max_length=260, storage=OverwriteStorage())
    

class OverwriteStorage(FileSystemStorage): #this is actually above
    def get_available_name(self, name, max_length=None):
        self.delete(name)
        return name

forms.py:

class TemplateAdminForm(forms.ModelForm):
    def __init__(self,*args,**kwargs):
        super().__init__(*args, **kwargs)

    class Meta:
        model = Template
        fields = ["name", "file", ]

    def clean(self):
        cleaned_data = super().clean()

        upFile = Path(str(cleaned_data["file"]))
        if upFile.suffix == ".zip":
            path = self.instance.get_folder(cleaned_data["name"])
            logging.error(f"path")
            unpack_zip(path) ## works! the directory is created/filled  
        else:
            raise forms.ValidationError("unknown file type ...")
        logging.error("DONE!") # I see this output 
        return cleaned_data  

## signal to see when the error might be happening:
@receiver(post_save, sender = Template)
def testing(sender, **kwargs):
    logging.error("we never get here")

settings.py:

TEMPLATES_FOLDER = PATH(MEDIA_ROOT).joinpath("TEMPLATES")

但是:

ERROR:django.security.SuspiciousFileOperation:Detected path traversal attempt in '/opt/project/media_root/TEMPLATES/some/some' WARNING:django.request:Bad Request: /admin/appName/template/add/

编辑:

因为this discussion 这可能很重要,这发生在django 3.2.8

【问题讨论】:

【参考方案1】:

我在 Django 3.2.6 上以绝对路径名打开模式为“wb”的文件时遇到相同的错误,当我不使用我已阅读的临时文件时,为了避免此问题,建议使用我会链接this answer,以防它帮助您部署它并分享我的经验。

这里是建议的地方:answer

一种可能的解决方案是将该目录移动到 django 项目根文件夹下并使用相对路径对其进行寻址。我也会尝试使用它来了解您如何实现这一目标:

import os
print("WORKING DIRECTORY: " + os.getcwd())

关于此主题的一篇文章建议使用以下代码(在这种情况下处理图像文件时):link

from django.core.files.temp import NamedTemporaryFile
from django.core import files
image_temp_file = NamedTemporaryFile(delete=True)

in_memory_image = open('/path/to/file', 'rb')
# Write the in-memory file to the temporary file
# Read the streamed image in sections

for block in in_memory_image.read(1024 * 8):
    
    # If no more file then stop
    if not block:
        break    # Write image block to temporary file
    image_temp_file.write(block)


file_name = 'temp.png'  # Choose a unique name for the file
image_temp_file.flush()
temp_file = files.File(image_temp_file, name=file_name)

让我们看一下代码:

创建一个 NamedTemporaryFile 而不是 TemporaryFile,因为 Django 的 ImageField 需要文件名。 遍历您的内存文件并将数据块写入 NamedTemporaryFile 对象。 刷新文件以确保将文件写入存储。 将临时文件更改为 Django 的 File 对象。

您可以直接将此文件分配给 Django 模型并保存。

>>> from blog.models import Blog
>>> b = Blog.objects.first()
>>> b.image = temp_file
>>> b.save()

我个人解决了我的 SuspiciousFileOperation 问题,方法是使用 settings.py 中的“BASE_DIR”作为路径的开头(文件系统中没有高于该级别)、使用 NamedTemporaryFile 和使用模型 FileField save() 方法来解决我的目录适当地像这样:

# inside a model class save(self, *args, **kwargs) method
# file_name is the file name alone, no path to the file
self.myfilefield.save(file_name, temporary_file_object, save=False) # and then call the super().save(*args, **kwargs) inside the save() method of your model

【讨论】:

以上是关于Django 和 SuspiciousFileOperation:检测到路径遍历尝试的主要内容,如果未能解决你的问题,请参考以下文章

flask和django的对比

Django搭建个人博客平台2---创建一个Django项目和项目梳理

Django搭建个人博客平台2---创建一个Django项目和项目梳理

Django 和 Django 休息框架

django和wsgi的问题。

django.urls、django rest 和 django-cors-headers - 导入问题