向用户展示他们的密码不被允许的原因是否安全?

信息安全 密码 密码策略 用户界面 可用性
2021-08-28 22:09:10

////////////////////////////////////////////////////////////////////////////// ////////////

这个问题收到了很多点击,比我想象的在这样一个基本话题上的点击量要多。所以,我想我会告诉人们我在做什么。此外,我还在评论中看到我将密码存储为纯文本。只是为了澄清我不是。

我更新的验证功能:

public function is_password($str) {
        if (strlen($str) < 10) { // Less then 10
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (strlen($str) > 100) { // Greater then 100
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#[0-9]+#", $str)) { // At least 1 number
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#[a-z]+#", $str)) { // At least 1 letter
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#[A-Z]+#", $str)) { // At least 1 capital
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } elseif (!preg_match("#\W+#", $str)) { // At least 1 symbol
            $this -> set_message('is_password', 'Password must include at least one number, one letter, one capital letter , one symbol and be between 10 and 100 characters long.');
            return FALSE;
        } else {
            return TRUE; // No errors
        }     
    }

每次返回时FALSE,我总是告诉他们需要的整个密码。

只是为了回答一些关于为什么它这么长的问题:

为什么不这么久?我工作的人会使用句子。很长的那个。

我如何散列我的密码?/ 为什么要使用 100 个字符?-> 只使用更好的散列算法

对于 PHP,我正在使用最好的语言。我正在使用这个库,它是Anthony Ferrara创建的新密码哈希 API的 PHP 5.5 等价物。我使用这种散列的理由很简单,对 CPU 的要求非常高(如果你曾经在 Linux/Windows 机器上测试过,CPU 使用率是 100%)。此外,由于成本因素,该算法具有很强的可扩展尝试登录,我什至在通过登录屏幕之前就收到了 PHP 超时错误(这是一个愚蠢的成本因素)。杰里米·戈斯尼 ( Jeremi Gosney ) 所做的一项研究 (这是报告的 PDF 下载)与其他更流行的函数(是的,更流行的)相比,它测试了这个函数的强度,得出的结论是,即使使用 25 个 GPU,而使用 bcrypt 的成本为 5,密码散列是你的最后一个顾虑。我用17的成本...

如果有人感兴趣,我的功能(至少与该主题有关的部分):

public function create_user($value) {
        $this -> CI = get_instance();
        $this -> CI -> load -> library('bcrypt');

        foreach ($value as $k => $v) {// add PDO place holder to the keys
            $vals[":$k"] = $v;
        }
        $vals[":password"] = $this -> CI -> bcrypt -> password_hash($vals[":password"], PASSWORD_BCRYPT, array("cost" => 17)); // Take old $vals[":password"] and run it through bcrypt to come up with the new $vals[":password"] 

希望这个问题可以帮助其他人。

//////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////

我目前正在做一个新项目,遇到了一个问题。

披露您的密码要求是否安全?如果是这样,为什么它是安全的?

我有一个对密码进行验证的函数,每个步骤都向用户展示了验证不起作用的原因。

这是我的功能:

public function is_password($str) {
    if (strlen($str) < 10) {
        $this -> set_message('is_password', 'Password too short.');
        return FALSE;
    } elseif (strlen($str) > 100) {
        $this -> set_message('is_password', 'Password is too long.');
        return FALSE;
    } elseif (!preg_match("#[0-9]+#", $str)) {
        $this -> set_message('is_password', 'Password must include at least one number.');
        return FALSE;
    } elseif (!preg_match("#[a-z]+#", $str)) {
        $this -> set_message('is_password', 'Password must contain at least one letter.');
        return FALSE;
    } elseif (!preg_match("#[A-Z]+#", $str)) {
        $this -> set_message('is_password', 'Password must contain at least one capital letter.');
        return FALSE;
    } elseif (!preg_match("#\W+#", $pwd)) {
        $this -> set_message('is_password', 'Password must include at least one symbol.');
        return FALSE;
    } else {
        return TRUE;
    }
}

我对此的想法是,如果我们让“用户”/攻击者知道我的密码由什么组成,攻击者会不会更容易知道?我知道通过默默无闻的安全性不是最佳实践,但在这种情况下它可以成为一个强有力的论据吗?

我想知道我是否以正确的方式处理这件事。任何帮助都会很棒。

4个回答

如果您不泄露您的“密码要求”,那么您的用户会讨厌您。有些人无法成功找到“可接受的密码”,并会致电帮助台。或者,更糟糕的是,如果用户是客户,那么他们会去别处购买。杀死自己生意的好方法!

另一方面,如果泄露你的“密码要求”确实以不可忽视的方式帮助了攻击者,那么你的密码要求就非常糟糕:它们不仅会激怒用户,而且还会将用户限制在一个太小的可能范围内。密码。

请注意,攻击者通常可以很好地猜出您的“密码要求”是什么,例如通过尝试注册自己。

无论如何,“密码要求”会适得其反并降低安全性,除了可以合理证明的“最小长度”。所以不要那样做。密码安全的关键是用户教育,这可能有助于使用一些工具(例如用于强密码的随机生成器)。强制约束无济于事;并强制执行隐藏约束更糟。例如,如果您的规则要求至少有一个数字和一个符号,那么非常高比例的用户只会附加“1”。在他们的密码末尾;攻击者知道这一点。额外的后缀不会对密码熵增加太多(即攻击者必须尝试成功破解的潜在密码数量),但会消耗一些被称为“用户耐心”的稀缺资源:用户会更喜欢较短的密码,因为他们必须添加“1”。后缀以安抚您的服务器。

如果您没有准确地告诉用户他的密码需要什么来通过您的功能验证,他怎么知道要添加或修改什么才能使其有效?

提供此类信息可能会使暴力攻击更容易。但是,考虑到您的要求,它对攻击者根本没有帮助,因为有太多的密码可能性使攻击变得有价值。

一旦第三次尝试输入有效密码失败,用户/客户很可能会限制使用您的服务。相比之下,黑客会尝试任意注册,以尽可能准确地找出您的密码要求。

为了解决这个问题,首先通过通常的方式(电子邮件、验证码等)验证用户并向他们发送密码令牌。这已经减少了虚假有效用户的数量,并且通过在特定时间阻止过多的密码更改,您会使黑客的生活更加困难。但是,您仍应在第一次尝试输入无效密码后披露所有密码要求。

但更好的是,我建议不要强迫用户选择一个任意复杂的密码,他们最终只会在显示器旁边的便利贴上写下来(或者让他们将密码重置为简化的“登录”)。相反,让他们知道他们的密码很弱,告诉他们什么是好的但容易记住的密码(例如,使用密码代替)并允许他们在单击“是的,我知道我的密码不是很安全无论如何让我继续” - 如果帐户随后被黑客入侵,那是他们的错,在此明确警告之后您不应该承担责任。假设确实使用了正确且已建立的密码散列而不是 homebrew-crap 或更糟糕的是纯文本。

考虑一下场景——攻击者如何获得需求?很可能是因为他们可以自己注册。在这种情况下,对您的需求进行逆向工程是微不足道的,除非它们太复杂而无法在没有解释的情况下使用。所以,是的,让用户知道您的要求是安全的。

但更好的方法是根本不需要密码,如果可能的话,使用 OpenID。几乎可以肯定,它至少与您用于收集和存储密码的任何东西一样安全。对于任何拥有 gmail 或 yahoo 帐户的人来说,这肯定会更容易。