Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 安全用户提供的文件名_Python_File_Security_Directory - Fatal编程技术网

Python 安全用户提供的文件名

Python 安全用户提供的文件名,python,file,security,directory,Python,File,Security,Directory,我的应用程序的一部分要求客户端请求文件。现在,行为良好的客户端只会请求安全的文件,但我不希望用户提供。/../../../creditCardInfo.xls“。保护文件名以确保不会提供高于目录层次结构中某一点的文件的最佳实践/最简单方法是什么?本能的第一反应是不允许文件名中包含。,但这似乎。。。不完整和不令人满意 当前关于文件名安全的问题主要集中在创建一个可写/可读的文件名,而不是确保不应该访问的文件被访问。如果open使用与os.path.abspath相同的机制解析路径,那么这似乎是可行的

我的应用程序的一部分要求客户端请求文件。现在,行为良好的客户端只会请求安全的文件,但我不希望用户提供
。/../../../creditCardInfo.xls“
。保护文件名以确保不会提供高于目录层次结构中某一点的文件的最佳实践/最简单方法是什么?本能的第一反应是不允许文件名中包含
,但这似乎。。。不完整和不令人满意


当前关于文件名安全的问题主要集中在创建一个可写/可读的文件名,而不是确保不应该访问的文件被访问。

如果
open
使用与
os.path.abspath
相同的机制解析路径,那么这似乎是可行的。这种方法有什么缺陷吗

import os

def is_safe(filename):
    here = os.path.abspath(".")
    there = os.path.abspath(filename)
    return there.startswith(here)

>>> is_safe("foo.txt")
True
>>> is_safe("foo/bar/baz")
True
>>> is_safe("../../goodies")
False
>>> is_safe("/hax")
False

如果您在UNIX变体中运行,则可能需要一个阻止在应用程序外部访问系统的命令


这种方法将避免您必须编写自己的代码来处理问题,并允许您通过基础架构设置来处理问题。如果您需要限制对应用程序中某个区域的访问,因为它会更改进程认为是系统根的内容,那么这可能不合适。

我认为您正在寻找一种方法来查找文件的规范(*)路径。也就是说,删除了
和符号链接。这就是我们的角色

realpath
将遵循符号链接并“减少”路径:

sylvain@daal:~$ ln -s /etc/password z
sylvain@daal:~$ python 
Python 2.6.6 (r266:84292, Dec 26 2010, 22:31:48) 
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import os.path
>>> os.path.realpath("z")
'/etc/password'
>>> os.path.realpath("z/..")
'/etc'
>>> os.path.realpath("./Documents/../z/..")
'/etc'
。。。而
normpath
很容易被滥用:

>>> os.path.normpath("./Documents/../z/..")
'.'
一旦获得了规范名称,就可以轻松地检查用户是否应该有权访问请求的文件。与白名单进行比较


(*)一个文件可能有不同的路径,但只有一个规范路径。

有关更多信息,请参阅。

以下是我使用的方法,我认为这种方法的好处是可以轻松控制对文件的访问,并防止路径操纵

用户上载文件时:

  • 读取文件名
  • 生成随机字母数字标记
  • 使用该令牌的文件名将文件保存在不可通过web访问的目录中
  • 在数据库中记录令牌和原始文件名(以及谁上传了它,或者以某种方式指示谁有权使用它)
  • 要获取文件,请执行以下操作:

  • 用户通过令牌而不是文件路径请求文件(mysite.com/download/587and83j21h1)
  • 对令牌使用白名单验证以确保其为字母数字
  • 检查用户对请求文件的权限
  • 将文件写入响应流,并将文件名设置为原始文件名

  • 定义“安全”。不从更高层次传递文件是唯一的标准?@kirelagin:hmm。。我想他们应该只能从给定的
    resources
    目录请求文件,但在该目录中,他们可以访问任何他们喜欢的内容。如果服务器在Windows上运行,也应该禁止从其他驱动器号获取文件这种方法似乎很脆弱。我认为在面对符号链接(特别是指向路径名内部组件中目录的符号链接)、绑定挂载等时,很难保证它是正确的。。。解决这一问题的一种方法是在实际的
    open
    中使用
    os.path.abspath
    的结果,而不仅仅是在安全检查中。但更具体地说,如果pwd是
    /a/foo
    ,您的函数认为
    /a/foobar
    是安全的,我认为这是一个问题,因为
    /a/foobar
    不在目录
    /a/foo
    中。实际上,不,这是
    os.path.normpath
    的角色,它由
    os.path.abspath
    调用。但是,是的,解决符号链接也是一个好主意。@kirelagin我对自己很有信心。现在我有一个疑问。因此,我重新阅读了文档,似乎
    normpath
    仅通过字符串操作删除
    。正如doc所说,“这个字符串操作可能会改变包含符号链接的路径的含义”。通过测试,似乎
    realpath
    首先遵循符号链接,然后根据需要减少路径。你真的可以将“用户文件”放在chroot监狱中,而将“程序文件”放在外面吗?假设我有一个在chroot监狱中运行的web应用程序,该应用程序如何访问监狱外的配置文件(或模板文件,或任何文件)?
    >>> os.path.normpath("./Documents/../z/..")
    '.'