【问题标题】:Regex to check if a path go only down正则表达式检查路径是否仅向下
【发布时间】:2011-09-25 12:26:04
【问题描述】:

我想测试用户给出的路径是否像这样:

my/down/path

在对面:

this/path/../../go/up

出于安全原因。

我已经做了这个:

return (bool)preg_match('#^([a-z0-9_-])+(\/[a-z0-9_-])*$#i', $fieldValue);

但是应该允许用户在他的路径中使用'.'(例如:my/./path,这没什么用但他可以),我不知道如何考虑。

然后我正在寻找一个安全的正则表达式来检查这个。

谢谢

编辑:在查看答案后,如果测试检查真实路径(删除 '.''..')是否是下行路径,那就没问题了。

【问题讨论】:

  • 我添加了 [security] 标签,它应该会引起问题的更多关注,并且希望可能来自知道良好 PHP 路径遍历库的人。正如我的回答所暗示的,这是一个不平凡的问题。

标签: php regex security path filepath


【解决方案1】:

您可以简单地检查用户提供的路径的真实路径是否以允许的路径开头:

function isBelowAllowedPath($allowedPath, $pathToCheck)
{
    return strpos(
        realpath($allowedPath . DIRECTORY_SEPARATOR . $pathToCheck), 
        realpath($allowedPath)
    ) === 0;
}

Demo on codepad

请注意,对于$allowedPath 下面不存在的目录,这也会返回false

【讨论】:

  • 取决于您对realpath 的确切需求,这可能不适用。 realpath 要求路径名存在,即您不能使用此检查来创建新路径。此外,realpath 将在 Phar 档案等某些边缘情况下失败。
【解决方案2】:

您可能不想检查路径是否不包含..,而是想检查如果作为整体评估,它不会上升。例如。 ./path/.. 仍在 . 中,即使它包含 ..

你可以找到path depth validation in Twig的实现:

$parts = preg_split('#[\\\\/]+#', $name);
$level = 0;
foreach ($parts as $part) {
    if ('..' === $part) {
        --$level;
    } elseif ('.' !== $part) {
        ++$level;
    }

    if ($level < 0) {
        return false;
    }
}

return true;

Twig 不使用realpath 进行验证,因为realpath 在 Phar 档案中的路径存在问题。此外,realpath 仅在路径名已存在时才有效。

【讨论】:

  • 我添加了一个区分路径深度验证和路径遍历验证的响应。对您的回复没有任何个人意见,但由于 OP 提到了安全性,我希望至少有一个解决更多敌对环境的答案。
【解决方案3】:

先前的响应(包括接受的响应)地址路径深度但不是路径遍历。由于问题特别提到这是出于安全考虑,因此到目前为止所述的随意检查可能还不够。

例如,

  • 您是否关心遍历当前工作目录下的硬链接或软链接?
  • 您所在的系统(或可能部署到的系统)是否支持 unicode?​​li>
  • 在您的 PHP 代码看到该字符串之前或之后,有多少事情正在评估该字符串?网络服务器?贝壳?还有什么?

假设我向您的脚本发送一个字符串,例如./..%2f../?这个字符串将我提升两个级别对您的应用程序很重要吗?或者其他答案中提供的脚本不会捕捉到这一点,因为它没有评估为..

./\.\./ 呢?如果通过拆分\/ 来解析路径,则接受的答案中的脚本不会捕获它,因为每个部分看起来都像.,这只是当前目录。但是典型的 UNIX shell 将 \ 视为转义字符,因此传递它 ./\.\./ 等效于 ./../,因此攻击者可以利用脚本结合了 UNIX 和 Windows 样式路径的测试这一事实。

如果您所说的“安全性”真的是指您想提供针对偶然错误和拼写错误的保护,那么其他答案可能就足够了。如果您正在为恶劣的环境进行编程并希望防止故意攻击造成的破坏,那么它们几乎不会触及表面,建议您阅读 OWASP 的安全编程知识。我将从他们的articles on Path Traversal 开始,然后阅读他们概述的其他攻击以及如何避免它们,更重要的是,如何测试它们。

【讨论】:

  • 我想看看这是否适用于存储在 PHP 字符串中并传递给 PHP 文件系统处理函数之一的路径的参考。更准确地说:我真诚地怀疑,如果我将字符串传递给 PHP 中的 FS 函数,它将执行 URL 解码或将反斜杠解释为转义序列。但我很想被证明是错误的,因为这会对许多使用我上面发布的方法的库产生严重的安全影响。
  • 您是否点击了我提供的链接? OWASP 的示例是用 PHP 编写的。我还在我的回复中特别指出,确切的行为取决于在 PHP 获取字符串之后 之前处理 URL 的方式。如果许多公共库受到影响,我一点也不感到惊讶,因为 OWASP 十大 Web 应用程序安全风险中的第 8 名是未能限制 URL 访问,其中路径遍历是主要向量之一。如果流行的做法是合理的,这不会进入 OWASP 前 10 名。
  • 是的,我想让我的应用程序真正安全,我在 windows 下的本地工作,但它可以远程在 linux 上。我不明白你所说的一切,用户发布一个表单我得到值,我检查字段,然后例如显示文件匹配字段值。我假设 readfile(或任何 php 函数)将字符串 arg 解释为 php 代码中的任何其他字符串,例如测试“$str =='..'”。对于./\.\./ 拆分字符串,我已经创建了一个检查 DIRECTORY_SEPARATOR 常量并将 / 或 \ 替换为相反的函数。我认为它解决了问题。
  • 如果您从这篇文章和各种回复中没有得到任何其他信息,最重要的建议是:访问 OWASP 站点并深入了解 Web 应用程序安全性。 OWASP 不是该主题的唯一权威,但它确实是一个很好的起点。如果不深入了解、重用现有知识然后积极地对实施进行渗透测试,几乎没有机会获得正确的 Web 应用程序安全性。我的帖子的目的不是为您提供更多检查模式,而是说明为什么有必要更深入地了解该主题。
【解决方案4】:
$folders = $explode('/', $path);

if (in_array('..', $folders)) {
    print('Error: path contains ..');
}

【讨论】:

  • 使用 .. 仍然可能导致路径低于允许路径,例如当/only/data/below/here 然后/only/data/below/here/foo/.. 仍然可以。
  • @Gordon:如果不使用..,你会怎么走?
  • @PeeHaa,我猜:/path/to/dir/../../to/dir/samefile
  • @Rob W:但我检查路径是否包含..。所以这是不可能的。
  • /path/to/dir/../../to/dir/samefile = /path/to/dir/samefile,应该是有效的。
【解决方案5】:

如果您只想限制用户在路径层次结构中向上,您可以显式搜索'..':

if (1 === preg_match('/\.\./', $path)) {
    /* path contains .. */
}

这也比explode和in_array更快。

基准测试:

<?php

$attempts = 100000;
$path     = 'my/path/with/../invalid';

$t = microtime(true);
for ($i = 0; $i < $attempts; ++$i) {
  $folders = explode('/', $path);
  if (in_array('..', $folders)) {
    /* .. in path */ ;
  }
}
$end = microtime(true);
printf("in_array: %f\n", $end - $t);

$t = microtime(true);
for ($i = 0; $i < $attempts; ++$i) {
  if (1 === preg_match('/\.\./', $path)) {
    /* .. in path */ ;
  }
}
$end = microtime(true);
printf("preg_match: %f\n ", $end - $t);

in_array: 0.088750

预匹配:0.071547

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 2019-07-29
    • 1970-01-01
    • 2015-01-22
    相关资源
    最近更新 更多