1.5 文件操作

1.5.1【必须】文件类型限制

  • 通过白名单对上传或者下载的文件类型、大小进行严格校验。仅允许业务所需文件类型上传,避免上传木马、WebShell等文件。
  1. import os
  2. ALLOWED_EXTENSIONS = ['txt','jpg','png']
  3. def allowed_file(filename):
  4. if ('.' in filename and
  5. '..' not in filename and
  6. os.path.splitext(filename)[1].lower() in ALLOWED_EXTENSIONS):
  7. return filename
  8. return None

1.5.2 【必须】禁止外部文件存储于可执行目录

  • 禁止外部文件存储于WEB容器的可执行目录(appBase)。建议使用 tempfile 库处理临时文件和临时目录。

1.5.3 【必须】避免路径穿越

  • 保存在本地文件系统时,必须对路径进行合法校验,避免目录穿越漏洞
  1. import os
  2. upload_dir = '/tmp/upload/' # 预期的上传目录
  3. file_name = '../../etc/hosts' # 用户传入的文件名
  4. absolute_path = os.path.join(upload_dir, file_name) # /tmp/upload/../../etc/hosts
  5. normalized_path = os.path.normpath(absolute_path) # /etc/hosts
  6. if not normalized_path.startswith(upload_dir): # 检查最终路径是否在预期的上传目录中
  7. raise IOError()

1.5.4 【建议】避免路径拼接

  • 文件目录避免外部参数拼接。保存文件目录建议后台写死并对文件名进行校验(字符类型、长度)。

1.5.5 【建议】文件名hash化处理

  • 建议文件保存时,将文件名替换为随机字符串。
  1. import uuid
  2. def random_filename(filename):
  3. ext = os.path.splitext(filename)[1]
  4. new_filename = uuid.uuid4().hex + ext
  5. return new_filename