代码之家  ›  专栏  ›  技术社区  ›  Steve Clay

ascii“../”是否是在php中表示目录遍历的唯一字节序列?

  •  4
  • Steve Clay  · 技术社区  · 15 年前

    我有一个使用 $_GET 参数选择文件系统上的JS/CSS文件。

    如果我拒绝输入字符串包含的所有请求 ./ , \ 或者是一个不在可见的7位ASCII范围内的字节,当路径被传递到PHP的底层(基于C的)文件函数时,这是否足以防止父目录遍历?

    我知道 null-byte vulnerabilities 但是,是否有其他的替代/格式错误的字符编码技巧可能会受到这些检查的干扰?

    以下是基本思想(不是生产代码):

    $f = $_GET['f']; // e.g. "path/to/file.js"
    
    // goal: select only unhidden CSS/JS files within DOC_ROOT
    if (! preg_match('@^[\x20-\x7E]+$@', $f)     // outside visible ASCII
       || false !== strpos($f, "./")             // has ./
       || false !== strpos($f, "\\")             // has \
       || 0 === strpos(basename($f), ".")        // .isHiddenFile
       || ! preg_match('@\\.(css|js)$i@', $f)    // not JS/CSS
       || ! is_file($_SERVER['DOCUMENT_ROOT'] . '/' . $f)) {
        die();
    }
    $content = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/' . $f);
    

    更新: 我的问题实际上是关于C文件系统函数如何解释任意的ASCII序列(例如,如果有未记录的转义序列),但我认识到这可能依赖于系统,在实践中可能无法回答。

    我的活动验证还要求 realpath($fullPath) 从开始 realpath($_SERVER['DOCUMENT_ROOT']) ,确保文件在Doc_根目录中,但此发布的目标是放弃 realpath() (在各种环境中都被证明是不可靠的),同时仍然允许不寻常但有效的URI /~user/[my files]/file.plugin.js .

    3 回复  |  直到 14 年前
        1
  •  1
  •   troelskn    15 年前

    你自己说的,但是比较 realpath 对已知根的输入是我能想到的最佳解决方案。realpath将解析路径/文件系统的任何隐藏特性,包括符号链接。

        2
  •  5
  •   SLaks    14 年前

    为安全起见过滤输入时,始终使用白名单,而不是背光。

    您应该拒绝所有不匹配的路径 /^([A-Za-z0-9_-]+\/?)*[A-Za-z0-9_-]+\.(js)|(css)?$/ .

    这将只允许在每个段都有字母、数字或 _- .

        3
  •  1
  •   Jed Smith    15 年前

    可能需要重新设计一下,但即使你通过了 ../../passwd , basename() 会使它绝缘。然后,您可以将所有要服务的文件放在一个文件夹中。

    鉴于 ../../././././a/b/c/d.txt , basename($f) d.txt ;这种方法对我来说似乎更明智,而不是试图超过用户,忘记一个漏洞。