如何安全地将字符串连接到PHP中的路径?

时间:2014-01-06 15:06:52

标签: php string security code-injection

我有一个字符串的常量开头和一个变量结尾,我如何保护字符串,以便在我注入的字符串包含

../

以下是一个简短的示例代码:

$dir = 'my/base/path/';
$file = $dir . $userSelectedFilename;
unlink($file);

如果$userSelectedFilename'../../myFileName',我认为这会导致我的脚本实际上尝试取消链接两个目录级别my/myFilename的内容,这显然不是我想要允许的内容,我想要在任何情况下都要将其保留在基线my/base/path/之下。

4 个答案:

答案 0 :(得分:1)

您可以通过执行以下操作来过滤掉这些字符:

$file = preg_match("/\.\.\//", "", $file)

将删除字符串../

的出现次数

只是旁注,您应该找到一种允许用户选择要删除的文件的不同方式,而不是允许他们将路径作为字符串输入,也可以通过向他们显示他们可以删除的文件的目录列表或其他东西那样的。

答案 1 :(得分:1)

我建议如下,只有以下方法:

<?
$dir = 'my/base/path/';
$file = $dir . $userSelectedFilename;
if(strpos(realpath($file),realpath($dir)) === 0) && is_file($file)) { // beware of the three ===
  unlink($file);
}

为什么?

依靠realpath找出文件的真实位置是安全的,这样可以消除目录遍历/多字节双点等。

之后我们检查文件的reapath的开头是否真的是我们已经过期的目录(strpos)的开头。

之后我们还会检查文件是否真的是一个文件,而不是指向elswhere或类似内容的符号链接。

我已经看到字符消除解决方案被多字节字符串和类似攻击打破了。

到目前为止,这种方法可以承受所有这些。

答案 2 :(得分:0)

使用正则表达式验证..//../的字符串,如果正则表达式返回true,则不接受字符串:

function validatePath($path) {
    if(preg_match('#\/\.\.\/#',$path))
        return False;
}

答案 3 :(得分:0)

你可以这样做&#34; my/base/path/../../dir/&#34;,如果你想要&#34;真实&#34;路径使用这个:

 echo realpath($dir."../../dir/"); // my/dir

http://php.net/manual/en/function.realpath.php