我的应用程序的一部分要求客户端请求文件。现在,一个行为良好的客户端只会请求可以安全提供的文件,但我不希望用户提供"../../../creditCardInfo.xls"
。保护文件名以确保没有提供高于目录层次结构中某个点的文件的最简单方法是什么?第一直觉是禁止其中包含..
的文件名,但这似乎是......不完整且不满意。
关于SO上的文件名安全性的当前问题集中在制作可写/可读文件名,而不是确保访问不应访问的文件。
答案 0 :(得分:1)
如果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
答案 1 :(得分:1)
如果您在UNIX变体中运行,则可能需要chroot jail来阻止访问应用程序之外的系统。
这种方法可以避免您编写自己的代码来处理问题,并让您通过基础结构设置来处理它。如果您需要限制对应用程序中某个区域的访问权限,则可能不合适,因为它会更改进程认为是系统根目录的内容。
答案 2 :(得分:0)
我认为您正在寻找一种方法来查找文件的规范(*)路径。这是..
,.
并删除了符号链接。这是os.path.realpath
>>> os.path.realpath(".")
'/home/sylvain'
>>> os.path.realpath("..")
'/home'
>>> os.path.realpath("./Documents/../..")
'/home'
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/..")
'.'
获得规范名称后,您可以轻松检查用户是否应该有权访问所请求的文件。比较白名单。
(*)文件可能有不同的路径,但只有一条规范路径 有关详细信息,请参阅http://www.xyzws.com/Javafaq/what-is-the-difference-between-absolute-relative-and-canonical-path-of-file-or-directory/60。
答案 3 :(得分:0)
以下是我使用的方法,我认为这样可以轻松控制对文件的访问,并防止路径操作。
当用户上传文件时:
获取文件: