2

如果我选择大量文件策略,
那么我是否会遇到目录
遍历安全问题?

我需要写登录系统,
大量的文件策略意味着

制作大量的 id 文件并使用 scandir。

所以目录会有

aaa.txt(内容为 aaa_pass)
bbb.txt(内容为 bbb_pass)
ccc.txt(内容为 ccc_pass)

而当有人输入他的id时,
系统scandir该目录,
然后找到id文件。

但是,嘿,如果他以

“../../important.txt”?

那么他可以访问 ../../important.txt 吗?

4

3 回答 3

2

乍一看,您似乎正在走一条有点奇怪的路径来编写登录系统。我不确定文件系统上目录中的纯文本文件是否是明智的选择,如果没有其他原因只是它异常并且您可能会忽略在更常见的身份验证中已经考虑过的许多细微之处系统。例如,如果您想存储散列和加盐的密码,您需要考虑如何在您的方案中实现它,并且您可能会犯一个会导致安全问题的错误。但是,使用一个好的 PEAR 库,甚至 Zend Framework 中的 Zend_Auth 组件,将为您提供一个清晰且有据可查的起点。

无论如何,假设您有您在问题中描述的安排的理由,那么在这种情况下,basename() 函数可能就是您想要的。它将剥离除文件名本身之外的所有内容,以便他们无法像您在问题中描述的那样进行目录遍历攻击。

因此,如果来自用户的输入是:

../../重要的

你可以运行:

$cleanUsername = basename($input);
$filename      = '/path/to/password/files/' . $cleanUsername . '.txt';

if (file_exists($filename)) {
    [...]
}

有道理?

于 2009-06-11T15:40:51.153 回答
1

您可以在将用户名用作路径的一部分之前对其进行一些验证 - 例如只允许字母和数字,您可以使用正则表达式执行以下操作:

if (!preg_match('/^[a-zA-Z0-9]+$/', $username)) {
    //username is not valid
} else {
    //username is ok to use
}

另一种方法是在读取或写入之前对用户名进行哈希处理,例如:

$hash = sha1($username);

这样,用户可以将任何东西作为他们的用户名,并且不会有他们操纵文件查找行为的危险。用户名"../../important.txt"会给你一个哈希值"48fc9e70df592ccde3a0dc969ba159415c62658d",尽管源字符串很讨厌,但它是安全的。

于 2009-06-11T15:46:33.120 回答
1

如果您别无选择,只能使用此文件密码系统​​(假设您出于某种原因必须这样做),除了创建某种混淆文件名之外,您可能还希望创建与您的服务器具有相同扩展名的文件-side 语言以防万一——例如,如果您使用的是 PHP,您的文件名将是 john.php(或混淆的 'john'),内容可能是这样的:

<?php
    exit; // or maybe even a header redirect --
    /*password goes here*/
?>

当然,您的文件读取例程将需要解析我们在注释块中的短语。

这样,如果有人确实以某种方式到达该文件,它将永远不会呈现。

于 2009-06-11T18:06:20.210 回答