安全的PHP登录以防止重放攻击

时间:2015-09-11 21:11:10

标签: php security encryption hash

到目前为止,我一直在使用md5和sha1来加密我的PHP登录中的密码,但由于这些算法现在被认为已经过时且不再安全,我想构建一个带有PHP函数的新登录系统{{3 }和password_hash。但是,有一件事我无法找到这些功能的解决方案:为了使登录安全抵御重放攻击,仅仅为每个密码设置一个单独的盐是不够的。因为如果攻击者以某种方式窃听客户端和服务器之间的通信,他就可以像原始客户端一样将用户名和已加密的密码哈希发送到服务器。所以我的解决方案一直是创造一个额外的"盐" (我不知道我的意思是否有正式用语)只对单次登录尝试有效。因此,客户端从服务器获取两个盐(一个对于每个用户帐户始终相同,另一个每次不同),加密用户输入的密码并将散列发送到服务器。然后服务器检查这个哈希值(例如$ Hash == sha1($ HashFromDbWithFixedSalt。$ RandomHash))。然后创建一个新的$ RandomHash。因此,即使攻击者模仿用户的通信,他也无法获得不允许的访问权。

新的PHP函数确实支持salt,但我找不到用这两种方法实现旧解决方案的方法,因为DB中的散列将包含固定散列(每个用户帐户不同)但不是随机的哈希(仅对一次尝试有效)。有没有人有想法或者已经解决了这个问题?

修改

这就是我以前的做法:

新用户注册:

  1. 为此用户创建随机盐。
  2. 将md5($ password_in_cleartext + $ salt)和盐本身保存到数据库。
  3. 用户想要登录:

    1. 用户将其用户名发送到服务器
    2. 服务器从数据库中查找他的salt并创建一个额外的随机盐,它保存在$ _SESSION中。它将这两种盐发送给用户。
    3. 用户在客户端(通过JS)加密他的密码,如下所示:sha1(md5($ password_in_cleartext + $ salt_from_the_db)+ $ random_salt)。他将此哈希发送到服务器。
    4. 服务器检查sha1($ hash_from_the_db + $ random_salt)== $ hash_the_user_sent。如果它们不相等,它会创建一个新的random_salt并将其发送给用户(返回步骤3)。

2 个答案:

答案 0 :(得分:4)

password_hash会自动为每个密码生成一个盐。

不应将散列密码传递回用户或离开服务器。如果您关注流量嗅探或MITM attacks,请使用SSL / https。

听起来你还试图防范CSRF攻击。在这种情况下,您可以在用户第一次点击页面时设置随机令牌,并期望随每次请求一起发送(这将阻止无法访问令牌的网站代表发送请求)用户)。

答案 1 :(得分:4)

如果您没有使用SSL,那么您的登录信息将不安全。无论你使用的哈希算法多么不可逆,无论如何都有其他方法来破坏这种交互。

它不是你的哈希的大小,而是你用它做的事情。使用md5的编写良好的系统将比使用sha2的编写错误的系统更安全。

假设您已经使用SSL和HSTS进行预注册,以及一些可缓存的ssl-stripping-sensitive CSS但仍需要更高的安全性,或者您在具有远程SSL终止的共享服务器上运行,那么您当前的方法是有效的,您只需要升级哈希算法(以及分配用于存储哈希密码的空间)。但正如您所发现的那样,在应用会话盐哈希之前,您仍然需要回复存储盐+密码哈希(提示:会话ID是后者的良好熵源,但JavaScript不能访问会话值 - 生成会话ID服务器端的has以用作会话salt)。然后问题就变成了JavaScript中的哈希函数。