2

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

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

4

4 回答 4

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
于 2013-06-13T18:18:28.680 回答
1

如果您在 UNIX 变体中运行,您可能需要一个chroot jail来防止在您的应用程序之外访问系统。

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

于 2013-06-13T18:23:24.573 回答
0

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

当用户上传文件时:

  1. 读取文件名。
  2. 生成一个随机的字母数字标记。
  3. 使用该令牌的文件名将该文件保存在不可 Web 访问的目录中。
  4. 将令牌和原始文件名记录在数据库中(连同谁上传它,或以某种方式表明谁拥有它的权限)。

要获取文件:

  1. 用户通过令牌请求文件,而不是文件路径 (mysite.com/download/587and83j21h1)
  2. 对令牌使用白名单验证以确保它是字母数字的。
  3. 检查用户对请求文件的权限。
  4. 将文件写入响应流并将文件名设置为等于原始文件名。
于 2013-06-14T14:41:45.667 回答
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

于 2013-06-13T18:23:34.167 回答