Security //和//是唯一的文件系统符号链接吗?

Security //和//是唯一的文件系统符号链接吗?,security,filesystems,Security,Filesystems,我想检查一个文件系统路径相对于另一个路径是否有效和安全。因此,我想知道是否有其他特殊字符,如/../和/../,可能导致路径实际指向其他地方 如果这就是我所要担心的,那么快速替换这些字符,然后执行类似的操作来检查任何其他不好的文件系统字符应该可以正常工作吗 [^a-z0-9\.\-_] (在windows上,像C:\这样的东西也必须被允许) 使用案例是,我有一个文件夹,站点管理员可以在其中创建目录,我想强制他们只在该文件夹中创建目录。换句话说,不要偷偷摸摸地使用…path/uploads/..

我想检查一个文件系统路径相对于另一个路径是否有效和安全。因此,我想知道是否有其他特殊字符,如
/../
/../
,可能导致路径实际指向其他地方

如果这就是我所要担心的,那么快速替换这些字符,然后执行类似的操作来检查任何其他不好的文件系统字符应该可以正常工作吗

[^a-z0-9\.\-_]
(在windows上,像
C:\
这样的东西也必须被允许)


使用案例是,我有一个文件夹,站点管理员可以在其中创建目录,我想强制他们只在该文件夹中创建目录。换句话说,不要偷偷摸摸地使用
…path/uploads/../../../../var/otherfolder/
,如果你知道我的意思;)

您使用哪种语言

例如,在PHP中,您可以获取任何字符串的名称,然后将其与基本目录进行比较。若您发现基本目录是
realpath
的前缀,那个么您就可以开始了


尽管这仅适用于PHP,但您应该能够在其他语言中找到类似的方法。

答案取决于所使用的文件系统。在Windows上是不同的,在*nix上是不同的

例如,在基于Windows的桌面平台上,无效路径字符可能包括引号(“)、小于()、管道(|)、退格(\b)、空(\0)和Unicode字符16到18以及20到25


我不知道您使用的是哪种平台/语言,但如果您使用的是.NET,您可以通过调用获取文件名中无法显示的字符列表,以及通过调用路径中无法显示的字符列表。Windows/DOS上有几个奇怪的地方。打开这些都会读写到意外的地方。我没有尝试过.NET如何处理这些,但我想你会得到某种安全例外

CON   Console. Reads from keyboard, writes to screen.
      "COPY CON temp.txt", end input with ctrl-z.

PRN   Printer. (Defaults to LPT1?)
LPTn  Parallell ports.

AUX   "Auxiliary device." Have never seen anyone use this myself.

COMn  Serial ports.

NUL   /dev/null

Unix符号链接可能很棘手,甚至可能会在某些系统上创建以导致路径循环获取实际
inode
devno
编号的文件名,以查看两个路径名是否实际上是同一个文件。

您是否考虑过使用类似的方法?您可以创建称为“chroot”的方法“这将阻止人们走出它。这是由操作系统强制执行的,因此您不必自己编写。请注意,这仅适用于*nix和*nix的某些变体,它没有使其万无一失所需的所有安全功能(即有已知的转义方法)。用于解析路径,
,(在大多数情况下,
/
用于Unix,而
\
用于Windows)在解析路径方面,这些是您真正需要担心的主要问题。根据RFC3986,这是解析URI中相对路径的算法。在大多数情况下,它也适用于文件系统路径

一种算法,
remove\u dot\u segments

  • 使用现在附加的路径初始化输入缓冲区 组件和输出缓冲区初始化为空 绳子
  • 当输入缓冲区不为空时,循环如下:
  • 如果输入缓冲区以前缀
    “./”
    “/”
    开头, 然后从输入缓冲区中删除该前缀;否则,
  • 如果输入缓冲区以前缀
    “/。/”
    “/。”
    开头, 其中,
    是一个完整的路径段,然后替换该路径段 输入缓冲区中带有
    “/”
    的前缀;否则,
  • 如果输入缓冲区以前缀
    “/../”
    “/…”
    开头, 其中,
    ”。“
    是一个完整的路径段,然后替换它 在输入缓冲区中添加前缀
    “/”
    ,并删除最后一个 从输出中删除段及其前面的
    “/”
    (如果有) 缓冲器否则,
  • 如果输入缓冲区仅包含
    ”。“
    ”,则删除 来自输入缓冲区的数据;否则,
  • 将输入缓冲区中的第一个路径段移动到 输出缓冲区,包括初始的
    “/”
    字符(如果 任何)和任何后续字符,但不包括, 下一个
    “/”
    字符或输入缓冲区的结尾
  • 最后,输出缓冲区作为
    删除点段
  • 运行示例:

    STEP OUTPUT BUFFER INPUT BUFFER 1 : /a/b/c/./../../g 2E: /a /b/c/./../../g 2E: /a/b /c/./../../g 2E: /a/b/c /./../../g 2B: /a/b/c /../../g 2C: /a/b /../g 2C: /a /g 2E: /a/g STEP OUTPUT BUFFER INPUT BUFFER 1 : mid/content=5/../6 2E: mid /content=5/../6 2E: mid/content=5 /../6 2C: mid /6 2E: mid/6 步进输出缓冲器输入缓冲器 1:/a/b/c/../g 2E:/a/b/c/../g 2E:/a/b/c/../g 2E:/a/b/c/../g 2B:/a/b/c/./../g 2C:/a/b/./g 2C:/a/g 2E:/a/g 步进输出缓冲器输入缓冲器 1:mid/内容=5/。/6 2E:mid/内容=5/。/6 2E:mid/内容=5/。/6 2C:2006年年中 2E:2006年年中
    不要忘记,可以指定比父目录更多的
    。“
    段。因此,如果你试图解析一条路径,你最终可能会尝试解析到
    /
    之外,或者在Windows中,
    C:\
    我已经直接回答了这个问题,但正如Tom所说,你试图做的事本质上是危险的。您可能应该做的是一次创建一个目录。通过regexp验证器传递它,不要让他们使用点段。只需在表单中为目录名设置一个文本字段和一个“生成目录”按钮。让它们遍历目录树以创建子目录。通过这种方式,您可以完全确信这些文件正在向它们应该去的地方移动

    这样做的优点是可以同时在Windows和*nix上工作,而不需要
    chroot

    附录:

    假设您接受directorie,此Regexp将只匹配非法的目录名