保护用户提供的文件名

时间:2013-06-13 18:13:36

标签: python file security directory

我的应用程序的一部分要求客户端请求文件。现在,一个行为良好的客户端只会请求可以安全提供的文件,但我不希望用户提供"../../../creditCardInfo.xls"。保护文件名以确保没有提供高于目录层次结构中某个点的文件的最简单方法是什么?第一直觉是禁止其中包含..的文件名,但这似乎是......不完整且不满意。

关于SO上的文件名安全性的当前问题集中在制作可写/可读文件名,而不是确保访问不应访问的文件。

4 个答案:

答案 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)

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

当用户上传文件时:

  1. 阅读文件名。
  2. 生成随机字母数字标记。
  3. 将文件保存在具有该令牌文件名的非Web可访问目录中。
  4. 在数据库中记录令牌和原始文件名(以及上传者,或者某种方式表明谁有权使用它)。
  5. 获取文件:

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