可怕的'让我登录'和会话检查

时间:2011-08-03 15:07:49

标签: php mysql session

所以,我知道这已经完成了死亡,但我遇到的所有答案都非常令人困惑/相互矛盾,或者他们的解释是不完整的,我正在努力跟上这个我的自我使用所有可用的资源,但我想我已经迷失了。我想一劳永逸地澄清一下。感谢您提前耐心等待,因为这可能会让您有点啰嗦。

我的页面顶部有一个小的登录框,如果用户没有登录,它将保持不变。如果他们 登录,那么他们将会看到而不是登录框在他们的名字问候。

会话检查

首先,这里是一个图表(据我所知到目前为止)如何检查用户是否可以访问“仅限会员”的内容。 (此代码位于页面顶部,用于检查和设置变量,例如$loggedin = true;

Session Checking Diagram

就目前而言,我的$_SESSION['loggedin']只是用户名。根据我的理解,会话可以伪造或劫持来自同一个域,因此我知道这是非常不安全的(例如,攻击者可能会以某种方式创建一个包含不同用户名和会话的会话 - 即时访问该用户的东西)但是我不知道我应该如何检查会话。我可以想象这样做的唯一方法是每次加载页面时连接到数据库并检查MD5哈希或来自数据库的东西(并更新它)但我想这会产生大量不必要的服务器流量而且我我几乎可以肯定有更好的方法来做到这一点。

登录

以下是用户登录时发生的情况(以及是否显示问候语或登录框)。

Logging In Diagram

在大多数情况下,我对此部分非常可靠(我希望),但我不知道我的MD5哈希应该包含什么,以便以后能够重新检查数据库中的哈希值, cookie中的一个和新生成的哈希,以确保攻击者没有召唤出一个cookie。另外,如下面的评论中所述,我可能会废弃在哈希中使用IP地址允许用户保持从多个位置(例如,他们的手机和笔记本电脑)登录。

所以我的问题是:

  • 我该如何检查我的会话是不是假的?
  • 我应该如何检查我的饼干是不是假的?
  • 检查到位后,我的登录方法是否足够安全?
  • 我遗漏了什么重要的东西?

如果您有什么想问的话,请在评论中告诉我,我很乐意用尽可能多的信息来编辑我的问题。

3 个答案:

答案 0 :(得分:8)

您无法劫持会话的内容。如果您是中间人,那么您可以使用相同的会话ID充当用户。但是,对于任何类型的会话,此问题仍然有效。

如果你想防止中间人攻击,你应该使用HTTPS。

使用HTTPS保证:

  • 您的会话不是假的,因为攻击者几乎无法窃取某人的会话ID并将其用作自己的会话
  • 出于同样的原因,你的cookies不是假的
  • 您的登录方法是安全的,因为所有内容都是加密发送和接收的,这使得攻击者几乎不可能看到,修改或拦截从服务器发送和接收的数据

HTTPS的主要缺点是:

  • 您需要购买证书
  • 加密会在网络流量和资源使用方面增加一些开销
  • 通过HTTPS发送的数据不会被缓存

答案 1 :(得分:4)

非常好的插图问题!

关于PHP会话支持的注意事项是,它太依赖于cookie。 PHP自动设置一个cookie,其中包含PHP分配的会话ID。然后它会自动读取该cookie并加载会话。

现在,可以通过“中间人攻击”来劫持cookie(例如,参见Firesheep)。攻击者只需复制另一个人的cookie(与每个请求一起发送),并将其添加到自己的浏览器中。并且由于会话是通过cookie识别的,因此您可以通过这种方式劫持会话(攻击者将只使用与用户完全相同的会话)。或者你可以劫持“记住我”的cookie供以后使用。

防止此类劫持的唯一真正保障是拥有加密连接,即“https”连接。然后,来回发送的cookie数据将针对每个请求进行加扰,因此其他人无法复制其实际内容。

否则,您对如何将持久登录cookie与用户匹配有正确的想法(即cookie中的散列必须与数据库中的散列匹配)。对于会话检查,您不需要任何散列,因为会话数据本身永远不会离开服务器。所以你可以将$_SESSION['logged_in_user_id']设置为UID - 或者设置为false / null,如果它们没有登录。也就是说,如果cookie检出,或用户名/密码签出,则设置用户会话中的id作为一个简单的int。

对于“手动”登录,用户发送他/她的用户名和密码,你再次暴露在中间人的攻击中。和以前一样,只是拦截发送到服务器的数据。除非您使用加密连接,否则cookie和用户名/密码(以及其他所有内容)都将是明文,并且对攻击者而言可以清楚地读取。

小点:
对于散列算法,我会使用sha1而不是较旧的md5。对于数据库中的用户名/密码,将密码作为明文存储在数据库中绝不是一个好主意。如果您的数据库遭到破坏,攻击者可以只读取其中的所有内容,无论您的服务器与用户进行通信的安全程度如何。

你可能已经知道了所有这些,但以防万一:对于users表,将用户名存储为明文,但也生成一个salt(比如,哈希当前时间加上一个随机 - 但是常量! - 你定义的字符串,并重复哈希几次)。将salt存储在数据库中,并在散列密码时使用它。再次,反复多次哈希。最后,将散列密码存储在DB中。您将无法向他人发送密码,因为您也不知道(您只知道哈希值),但您可以实现“重置密码”选项,该选项会生成新的盐和随机字符串,然后像任何其他密码一样哈希。只需记住将新的未散列密码保留足够长的时间以便发送给用户。你想多次散列它的原因是,它使得使用rainbow table来“反转”散列是不可行的,即使你知道盐。如果您只使用md5并且没有盐来密码一次,那么查找散列并查看未散列的密码是什么是微不足道的(除非您的用户都非常聪明地使用非常长的随机密码在任何彩虹表中找到。)

长话短说:会话,cookie和用户名/密码都容易遭受同样的攻击。最实际的防范措施是使用SSL(因为,正如您所注意到的,IP地址会发生变化)。

另见其他答案。信息越多越好:)

答案 2 :(得分:3)

  

我应该如何检查我的会话是不是假的?

通过在创建时设置变量。

session_start();
if(empty($_SESSION) || !isset($_SESSION['notfake']){
   $_SESSION = array();
   session_regenerate_id();
   $_SESSION['notfake']=1;
}
  

我应该如何检查我的饼干是不是假的?

通过在数据库中检查它们。有一个相当长的标识符。除了阻止在短时间内拥有“非常多”无效cookie的IP之外,您还可以做其他事情。

  检查完成后,

我的登录方法是否足够安全?

取决于,你确实使用HTTPS做所有事情?另外,将session-cookie设置为仅https。

  

我遗漏了哪些重要内容?

对于重要操作(更改密码/电子邮件等),要求用户重新提供密码。另外,不要使用 plain 哈希,在散列之前向值添加一些固定字符串(= salt)以避免直接使用彩虹表。

相关问题