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:检测到路径遍历尝试的主要内容,如果未能解决你的问题,请参考以下文章
Django搭建个人博客平台2---创建一个Django项目和项目梳理