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

时间:2009-10-27 22:04:03

标签: security filesystems

我想检查文件系统路径是否有效且相对于另一个路径使用是否安全。所以我想知道是否还有其他特殊字符,例如/..//./,这些字符可能会导致路径实际指向其他位置。

如果这就是我要担心的事情,那么快速更换这些字符后跟这样的字符来检查是否有其他错误的文件系统字符应该正常工作?

[^a-z0-9\.\-_]

(在Windows上也需要C:\这样的东西)

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

7 个答案:

答案 0 :(得分:2)

您使用的是哪种语言?

例如,在PHP中,您可以获取任何字符串的realpath,然后将其与基本目录进行比较。如果你发现你的基础指示是realpath的前缀,那么你就可以去了。

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

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

例如,在基于Windows的桌面平台上,无效路径字符可能包括quote(“),小于(<),大于(>),pipe(|),退格(\ b),null( \ 0),和Unicode字符16到18和20到25。

我不知道您使用的是哪种平台/语言,但如果您使用的是.NET,则可以通过调用Path.GetInvalidFilenameChars获取不能在文件名中的字符列表以及不能在路径中使用的字符列表致电Path.GetInvalidPathChars

答案 3 :(得分:1)

Unix符号链接可能很棘手,甚至可以创建以在某些系统上引起路径循环。您应lstat()使用文件名来获取实际的inodedevno数字,以查看两个路径名是否实际上是同一个文件。

答案 4 :(得分:1)

您是否考虑使用chroot之类的内容?您可以创建一个名为“chroot jail”的东西,以防止人们进入它。这是由操作系统强制执行的,因此您不必自己编写。请注意,这仅适用于* nix,并且在* nix的某些变体上,它没有使其变得万无一失的所有必要安全功能(即,有已知的转义方法)。

答案 5 :(得分:1)

对于解析路径,...(在大多数情况下,Unix为//,Windows为\\)是您真正需要的主要内容在解决路径方面担心。从RFC 3986开始,这是用于解析URI中的相对路径的算法。在大多数情况下,它也适用于文件系统路径。

算法remove_dot_segments

  1. 使用现在附加的路径初始化输入缓冲区 组件和输出缓冲区初始化为空 字符串。
  2. 虽然输入缓冲区不为空,但循环如下:
    1. 如果输入缓冲区的前缀为"../""./", 然后从输入缓冲区中删除该前缀;否则,
    2. 如果输入缓冲区的前缀为"/./""/.", 其中"."是完整路径段,然后替换它 输入缓冲区中带有"/"的前缀;否则,
    3. 如果输入缓冲区的前缀为"/../""/..", 其中".."是完整路径段,然后替换它 输入缓冲区中带有"/"的前缀,并删除最后一个 段及其前面的"/"(如果有的话)来自输出 缓冲;否则,
    4. 如果输入缓冲区仅由"."".."组成,则删除 来自输入缓冲区;否则,
    5. 将输入缓冲区中的第一个路径段移动到结尾 输出缓冲区,包括初始"/"字符(如果 任何)和任何后续角色,但不包括, 下一个"/"字符或输入缓冲区的结尾。
  3. 最后,输出缓冲区作为结果返回 remove_dot_segments
  4. 示例运行:

    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
    

    不要忘记,可以执行指定更多".."段而不是父目录的操作。因此,如果您尝试解析路径,最终可能会尝试解决/以外的问题,或者在Windows的情况下,C:\

答案 6 :(得分:1)

我已经直接回答了这个问题,但正如汤姆所说,你要做的事情本质上是危险的。你可能应该做的是一次创建一个目录。将其传递给regexp验证器,不要让它们使用点段。只需在目录名称的表单中有一个文本字段和一个“Make Directory”按钮。让他们遍历目录树以创建子目录。通过这种方式,您可以绝对确信文件正在应该使用的位置。

这样做的好处是可以在Windows和* nix上工作而无需chroot

<强>附录

此Regexp仅匹配非法目录名称,假设您一次接受一个目录:

/^(\.\.?|.*?[^a-zA-Z0-9\. _-]+.*?|^)$/

有效目录名称:

  • “这是一个目录”
  • “隐藏”
  • “example.com”
  • “2009年10月28日”

目录名无效:

  • “”
  • “”
  • “..”
  • “../某处/否则”
  • “/ etc / passwd的”
  • “将:?!被拒绝; OS”