可怕的“保持login”和会话检查

所以,我知道这已经被处死了,但是我所遇到的所有答案都是相互混淆/相互矛盾的,或者他们的解释是不完整的,我试图用自己的所有资源可用,但我想我已经迷路了。 我想一劳永逸地澄清这一点。 感谢您的耐心提前,因为这可能会有一点点啰嗦。

我的页面顶部有一个小的login框,如果用户没有login,它将保持不变。如果他们已经login,而不是login框,他们会看到一个问候与他们的名字。

会话检查

所以首先,这里是一个(到目前为止我的理解)如何检查用户可以访问“仅限会员”内容的图表。 (这段代码放在页面的顶部来检查和设置variables,如$loggedin = true;

会话检查图

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

在login

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

登录图

大多数情况下,我在这部分(我希望)是相当稳固的,但我不知道我的MD5哈希应该包含为了能够以后重新检查与数据库中的散列cookie和新生成的散列,以确保cookie没有被攻击者召唤。另外,正如下面的评论所述,我可能会放弃在散列中使用IP地址,以允许用户保持从多个位置login(例如,他们的电话和他们的笔记本电脑)。

所以我的问题是:

  • 我应该怎么检查我的会话是不是假的?
  • 我应该如何检查我的cookies不是假的?
  • 检查到位后,我的login方法是否足够安全?
  • 我有什么重要的东西被遗漏了吗?

如果有什么你想问的,请让我知道在评论中,我会很乐意编辑我的问题,尽可能多的信息,我可以提供。

你不能劫持会议的内容 。 如果您是中间人,那么您可以使用相同的会话ID作为用户。 但是,这个问题对任何一种会话都是有效的。

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

使用HTTPS保证:

  • 你的会话不是假的,因为攻击者实际上没有办法窃取某人的会话ID并将其用作自己的会话ID
  • 你的cookies不是假的,出于同样的原因
  • 您的login方法是安全的,因为一切都被发送和接收encryption,这使得攻击者几乎不可能看到,修改或拦截从服务器发送和接收的数据

HTTPS的主要缺点是:

  • 你将需要购买一个证书
  • encryption会增加一些开销,无论是在networkingstream量和资源使用情况
  • 通过HTTPS发送的数据不会被caching

非常好的插图问题!

关于PHP会话支持的事情要注意的是它也依赖于cookie。 PHP使用PHP分配的会话标识自动设置一个cookie。 然后它会自动读取该cookie并加载会话。

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

防止这种劫持的唯一真正的保障是有一个encryption的连接,即“https”连接。 然后,来回发送的cookie数据将被加扰为每个请求,所以别人不能复制其实际内容。

否则,如何将持久logincookie与用户进行匹配(即,cookie中的哈希值必须与数据库中的哈希值相匹配),才有正确的想法。 对于会话检查,您不需要任何散列,因为会话数据本身永远不会离开服务器。 所以你可以设置$_SESSION['logged_in_user_id']到UID – 如果它们没有login,也可以设置$_SESSION['logged_in_user_id'] false / null。也就是说,如果cookie检出或者用户名/密码检出,然后设置会话中的用户标识为简单的int。

至于“手动”login,用户发送用户名和密码的地方,在中间人攻击中,你再次暴露在人身上。 像以前一样,这只是一个拦截发送到服务器的数据的问题。 除非您使用encryption连接,否则Cookie和用户名/密码(以及其他所有内容)都将是明文的,并且攻击者可以清楚地读取它们。

小点:
对于哈希algorithm,我会用sha1而不是老的md5 。 而对于数据库中的用户名/密码,将密码作为明文存储在数据库中永远不是一个好主意。 如果您的数据库被攻破,攻击者可能只是读取所有内容,无论您的服务器如何安全地与您的用户进行通信。

你可能已经知道所有这些了,但以防万一:对于用户表,存储用户名为明文,但也生成一个盐(例如,散列当前时间加上一个随机 – 但常量! – 你定义的string,并散列反复几次)。 将salt存储在数据库中,并在对密码进行散列时使用它。 而且,再次重复多次。 最后,将散列的密码存储在数据库中。 你不能发送他们的密码,因为你也不知道(你只是知道哈希),但你可以实现一个“重置密码”选项,它会产生一个新的盐和一个随机的string,然后你像其他任何密码哈希。 只要记住将新的未哈希密码保持足够长的时间以发送给用户。 你想多次散列的原因是,即使你知道盐,使用彩虹表 “颠倒”哈希也是不可行的。 如果你只是密码一次,使用md5而不使用salt,那么查找散列值并查看未encryption的密码是否微不足道(除非你的用户足够聪明,可以使用非常长且随机的密码发现在任何彩虹表)。

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

另请参阅其他答案。 越多的信息越好:)

我应该怎么检查我的会话是不是假的?

通过创build一个variables。

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

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

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

检查到位后,我的login方法是否足够安全?

取决于,你确实使用HTTPS? 另外,将session-cookie设置为仅限https。

我有什么重要的东西被遗漏了吗?

对于重要的操作(更改密码/电子邮件/等),要求用户重新提供密码。 此外,不要使用普通散列,在散列之前添加一些固定的string(= salt)以避免直接使用彩虹表。