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/..")
'.'
一旦获得了规范名称,就可以轻松地检查用户是否应该有权访问请求的文件。与白名单进行比较
(*)一个文件可能有不同的路径,但只有一个规范路径。
有关更多信息,请参阅。以下是我使用的方法,我认为这种方法的好处是可以轻松控制对文件的访问,并防止路径操纵 用户上载文件时:
定义“安全”。不从更高层次传递文件是唯一的标准?@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/..")
'.'