如果我选择了很多文件策略,
然后我变得有目录
遍历安全问题?
我需要写登录系统,
许多文件策略意味着
制作大量的id文件并使用 SCANDIR。
所以目录会有
aaa.txt(内容为aaa_pass)
bbb.txt(内容为bbb_pass)
ccc.txt(内容为ccc_pass)
当有人输入他的身份时,
系统scandir目录,
然后找到id文件。
但是嘿,如果他进入
怎么办?“../../ important.txt”?
然后他可以访问../../important.txt?
答案 0 :(得分:2)
乍一看,您似乎正在编写一个登录系统的奇怪路径。我不确定文件系统目录中的纯文本文件是一条明智的路径,除非它是异常的,否则你可能会忽略许多已经在更常见的身份验证中考虑过的细微之处系统。例如,如果你想存储密码哈希和盐渍,你需要考虑如何在你的方案中实现它,你可能会犯一个导致安全问题的错误。但是,使用一个好的PEAR库甚至是Zend Framework的Zend_Auth组件,可以为您提供一个清晰且记录良好的起点。
无论如何,假设您有自己在问题中描述的安排的原因,在这种情况下,basename()函数可能就是您想要的。它将删除除文件名本身之外的所有内容,以便它们不会像你在问题中描述的那样进行目录遍历攻击。
因此,如果用户的输入是:
../../重要
你可以运行:
$cleanUsername = basename($input);
$filename = '/path/to/password/files/' . $cleanUsername . '.txt';
if (file_exists($filename)) {
[...]
}
有意义吗?
答案 1 :(得分: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"
的哈希值,尽管源字符串很糟糕,但这是一个安全的。
答案 2 :(得分:1)
如果除了使用此文件密码系统别有其他选择(假设您必须出于某种原因),除了创建某种模糊文件名外,您可能还希望创建具有相同扩展名的文件作为您的服务器端语言,以防万一 - 例如,如果您使用PHP,您的文件名将是john.php(或混淆'john'),内容可能是这样的:
<?php
exit; // or maybe even a header redirect --
/*password goes here*/
?>
当然,您的文件读取例程需要解析注释块内的短语。
这样,如果某人以某种方式到达该文件,它将永远不会呈现。