PHP:推荐的方法来转义路径中的斜杠(例如,防止目录遍历攻击)

时间:2016-02-28 21:42:03

标签: php escaping directory-traversal

我正在寻找一个PHP函数来将字符串清理成安全有效的文件名而没有目录分隔符(斜杠)。

理想情况下,它应该是可逆的,并且不应该超过必要的名称。

当然我想防止故意的目录遍历攻击。但我也想防止创建子文件夹。

我认为urlencode()会起作用,但我想知道这是否足够,和/或是否有更好或更受欢迎的东西。

此外,如果在Windows上有一些同样有效的东西(反斜杠作为目录分隔符) - 所以解决方案是可移植的。

用例/情景:

作为数据导入的一部分,我想将远程URL中的文件下载到本地文件系统中。网址来自csv文件。大多数都没问题,但它们可能包含比预期更多的斜杠。

E.g。大多数都是这样的:
https://files.example.com/pdf/12345.pdf

但是个别文件可能是这样的:
https://files.example.com/pdf/1/2345.pdf

这些文件都应该进入同一目录,例如 https://files.example.com/pdf/12345.pdf - > /destination/dir/12345.pdf

1/2345.pdf这样的文件不应该导致子目录。相反,/应该以某种(可逆的)方式进行转义。例如。使用urlencode(),这将是1%2F2345.pdf

3 个答案:

答案 0 :(得分:2)

您可以创建一组替换。例如,您可以使文件名中出现的/ char用其他类似的东西来表示,例如"(斜杠)"。只需使用str_replace在查找文件名和将文件名编码为url之间切换。这只是一个例子。

答案 1 :(得分:2)

这应该对你有帮助。

输入https://files.example.com/pdf/1/2345.pdf

输出:pdf_1_2345.pdf

$url = 'https://files.example.com/pdf/1/2345.pdf';
$parse = parse_url($url);

//get path, remove first slash
//$path: pdf/1/2345.pdf
$path = substr($parse['path'],1);

//result becomes: pdf_1_2345.pdf
$result = str_replace('/','_',$path);

编辑:最好的办法是将远程文件URL存储在数据库中,散列其值(使用md5或类似)并在本地保存该名称下的文件,并将该散列值存储在数据库中。

这是你最好的选择,这样你总能知道哪个远程文件对应你的本地文件,反之亦然,你不必在本地处理文件名,因为它们可能是你想要的任何东西(只要你检查它们的唯一性)

Database Table:
--------------------
| id | remote_url                  | local_name     |
-----------------------------------------------------
| 1  | http://example/.../123.pdf  | sdflkfd..dl.pdf|

你明白了。

答案 2 :(得分:0)

您可以使用此功能,它用下划线替换所有目录分隔符。

function secureFilePath($str)
{
    $str = str_replace('/', '_', $str);
    $str = str_replace('\\', '_', $str);
    $str = str_replace(DIRECTORY_SEPARATOR, '_', $str); // In case it does not equal the standard values
    return $str;
}