这是一种安全的方法吗,哎呀


Is this a secure method, oop

    $salt = $this->get_salt($username);
    if (is_null($salt)) {
        return FALSE;
    }
    $password = sha1(SITE_KEY . $password . $salt);
    $sth = $this->db->prepare("SELECT id, username, active FROM user WHERE username = ? AND password = ?");
    $sth->setFetchMode(PDO::FETCH_OBJ);
    $sth->execute(array($username, $password));
    if (($result = $sth->fetch()) !== FALSE) {
        return $result;
    }
    return FALSE;

这就是让我担心的原因:

我没有误解登录方法。我只是认为不应该 返回该对象。我可能是错的,你正在做的事情是完美的 很好,但我对此表示怀疑。您正在从 数据库、密码和所有内容都到可能不安全的脚本中。有人 可能会创建一个新文件,然后执行类似操作 var_dump($userObject(;并拥有所有这些信息

另外,我只是发现从中返回"魔术"属性是不直观的 东西。这只是另一件未经验证的事情 在使用之前。如果要将其移动到单独的方法 您的身份验证类并让它返回您可以运行的"活动"值 无需登录即可进行的任何验证.php脚本是任何 更聪明。

:再看一遍,虽然你已经需要知道 登录信息(如果您以这种方式滥用该对象(。是的 在我看来,最好将其分开,以防万一 的泄漏。不是说我知道有人怎么能做到。只 把它想象成一个潜在的漏洞。

我不假装理解恶意用户会如何做某事。 我只知道让他们更容易这样做似乎并不明智。 也许它没有任何问题,我不是安全专家。 我只是在戳一些东西,如果我要写它,我会改变 因为它们对我来说似乎很危险。如果你真的想知道它是否是 危险与否,我建议将该示例提交给常规 堆栈溢出社区,看看他们怎么说。

他说的话有道理吗?该方法将在我拥有的页面控制器中使用:

$user = $auth->login('username, password)
if ($user) {
//do some additional checks... set session variables
}

不,您提供的代码不安全。

首先,您使用的是非迭代简单哈希。 请参阅此答案和此博客文章以获取有关原因的信息。

第二,为什么要单独储存盐? 盐对于每条记录必须是唯一的,才能使其正常工作。 因此,放置它的逻辑位置是密码旁边。 在这种情况下,您正在进行两个查询而不是一个查询(假设盐不是从用户名派生的,并且确实是随机的(。 如果不是随机的,它应该是随机的。 有关更多信息,请参阅此帖子...

第三,您面临针对密码哈希的定时攻击,因为数据库未使用定时免疫比较。有关详细信息,请参阅本文和本文。

不要自己做这件事。 这真的很难安全地做到。 使用库。 您可以使用PHPASS或PHP-PasswordLib...

编辑:到您朋友的评论:

我没有误解登录方法。我只是认为它不应该返回该对象。我可能是错的,你做的很好,但我对此表示怀疑。您将数据库、密码和所有内容中的完整用户对象返回到可能不安全的脚本。有人可能会创建一个新文件,然后执行类似 var_dump($userObject(;并拥有所有这些信息

这是一个有效的观点。 但是在这一点上,如果用户可以注入var_dump($userObject),他可以运行$this->db->prepare("SELECT * FROM user");并获取所有用户数据,而不仅仅是他的。 因此,虽然这是需要指出的事情,但试图确保是不值得的。 除非你真的得到了肛门,并将其全部放入数据库中的存储过程中,并且从表中进行了有限的读取访问(因此您根本无法从用户表中进行选择(。 但是在这一点上,您需要从头开始重新设计整个应用程序,因为除非通过SP之外,您将永远无法获取任何用户信息。 而且很难做好(复杂性是安全的敌人(。

最后,我认为你首先会更好地防御脚本注入。 特别是如果你没有专业的管理员,他们可以保护你的服务器到防止这种攻击所需的荒谬数量(PHP进程上的chroot监狱等(。

另外,我只是觉得从某物中返回"魔法"属性是不直观的。这只是在使用前未经验证的另一件事。如果您要将其移动到身份验证类中的单独方法并让它返回"active"的值,则可以在没有登录的情况下运行所需的任何验证.php脚本更明智。

有什么神奇的属性? 您是否直接使用这些项目? 或者您是否使用它们来填充用户对象(然后知道如何处理数据(...? 只是那个剪裁,我看不出你朋友所指的问题......

:再次查看它,虽然如果您以这种方式滥用该对象,您已经需要知道登录信息。在我看来,最好将其分开,以防出现某种泄漏。不是说我知道有人怎么能做到。只要把它想象成少一个潜在的漏洞。

实际上,您只需要知道一个有效的用户名,由于上面确定的定时攻击......

我不假装理解恶意用户会如何做某事。我只知道让他们更容易这样做似乎并不明智。也许它没有任何问题,我不是安全专家。我只是在戳一些东西,如果我要写它,我会改变,因为它们对我来说似乎很危险。如果你真的想知道它是否危险,我建议将这个例子提交给常规的stackoverflow社区,看看他们怎么说。

总的来说,这是个好建议。 请记住,复杂性是安全的敌人。 因此,如果使其更难增加了很多复杂性,则添加新漏洞的机会要高得多(例如引入的定时攻击(。 我在简单方面犯了错误。 我有经过良好测试的库来处理复杂的部分(如密码哈希(,但我编写的代码很简单。

考虑最强大的加密算法:一次性键盘。 算法非常简单:

encrypted = plaintext XOR key

但是没有密钥就不可能解密。 因此,算法的安全性实际上在于秘密,而不是算法。 这就是你想要的。 算法应该是公开的,安全性不应该依赖于它的保密性。 否则,它就会通过默默无闻而成为安全感。 这给你一种温暖的模糊感觉,直到你被破解......

有关如何使用 bcrypt 对密码进行哈希处理,请参阅答案。它比你的更安全,因为它允许故意减慢哈希算法的速度(因此,如果有人试图蛮力,他们将被限制为每秒 1M 次左右的迭代,而不是 1B,这是小时和年之间的差异(。

此外,(与安全性无关(,您应该使用 PDO 的命名占位符,而不是未命名的占位符(:placeholder而不是 ? (。

此外,您可能希望构建一个完整的User对象并返回该对象,它将更容易使用(假设您有一个,您应该这样做!