防止会话劫持

如何防止多个客户端使用相同的会话ID? 我问这是因为我想添加一个额外的安全层来防止会话劫持在我的网站上。 如果黑客以某种方式计算出另一个用户的会话ID,并使用该SID发出请求,如何检测到在服务器上共享单个SID的不同客户端,然后拒绝劫持尝试?

编辑

我经过仔细考虑,已经接受了Gumbo的回答,因为我已经意识到由于无状态HTTP协议的限制,我所要求的是不可能的。 我忘了HTTP也许是最基本的原则,现在我想这个问题似乎有些微不足道。

让我详细说明我的意思:

用户A在example.com上login后,为了简单起见,他给了一些随机的会话ID,让它成为'abc123'。 此会话ID在客户端以cookie的forms存储,并通过服务器端会话进行validation,以确保login的用户在从一个网页移动到另一个网页时保持login状态。 如果HTTP不是无状态的,那么这个cookie当然不需要存在。 因此,如果用户B窃取用户A的SID,并在他的计算机上创build一个值为“abc123”的cookie,他将成功劫持用户A的会话,但服务器根本无法合法识别用户B请求与用户A的请求有任何不同,因此服务器没有理由拒绝任何请求。 即使我们要列出在服务器上已经激活的会话,并尝试查看是否有人正在访问已经处于活动状态的会话,我们如何确定是另一个非法访问会话的用户而不是同一个用户谁已经login了一个会话ID,但只是试图做出另一个请求(即导航到不同的网页)。 我们不能。 检查用户代理? 可以欺骗 – 但作为深度防御措施仍然是好的。 IP地址? 可以根据正当的理由进行更改,但是我build议不要检查IP地址,而应该检查IP的前两个八位字节,即使数据规划networking中的用户因为完全合法的原因而经常有不断变化的IP通常只有IP的最后两个八位字节发生变化。

总而言之,无状态HTTP谴责我们永远无法完全保护我们的网站免遭会话劫持,但良好的做法(如Gumbo提供的)将足以防止绝大多数的会话攻击。 试图通过拒绝同一个SID的多个请求来保护会话免受劫持是简单的可笑的,并且会破坏会话的整个目的。

不幸的是,没有有效的方法可以明确地识别与真实请求相反的来自攻击者的请求。 因为大多数对抗措施的属性检查如IP地址或用户代理特征不是可靠的(IP地址可能在多个请求之间改变),或者可以容易地被伪造(例如User-Agent请求头),因此可能产生不需要的误报(即,真正的用户交换IP地址)或者漏报(即攻击者能够用相同的用户代理成功伪造请求)。

这就是为什么防止会话劫持的最好方法是确保攻击者找不到其他用户的会话ID。 这意味着您应该devise您的应用程序和会话pipe理,以便(1)攻击者不能通过使用足够的熵来猜测有效的会话ID,以及(2)攻击者无法通过已知的攻击获取有效的会话ID诸如嗅探networking通信,跨站脚本,通过Referer泄漏等

这就是说,你应该:

  • 使用足够的随机input来生成会话ID(请参阅session.entropy_filesession.entropy_lengthsession.hash_function
  • 在传输过程中使用HTTPS来保护会话ID
  • 将会话ID存储在cookie中,而不是存储在URL中,以避免Referer泄漏(请参阅session.use_only_cookies
  • 使用HttpOnlySecure属性设置cookie以禁止通过JavaScript访问(如果存在XSS漏洞)并禁止通过不安全的通道进行传输(请参阅session.cookie_httponlysession.cookie_secure

除此之外,在某些会话状态发生变化(例如login后确认真实性或更改授权/特权)之后,还应该重新生成会话ID,同时使旧会话失效(请参阅session_regenerate_id函数 ),并且还可以定期执行此操作以减less时间跨越一个成功的会话劫持攻击。

我们可以做这样的事情吗?

将会话ID存储在数据库中。 还存储该会话ID的IP地址和HTTP_USER_AGENT。 现在,当请求到达包含匹配的会话ID的服务器时,请检查脚本中来自哪个代理和IP。

可以通过为会话创build通用函数或类来完成这项基础工作,以便在处理每个请求之前对其进行validation。 这几乎不需要一些微秒。 但是,如果许多用户正在访问您的网站,并且您拥有庞大的会话数据库,那么这可能不是什么性能问题。 但是,与其他方法(如=>使用再生会话)相比,它肯定会非常安全。

在重新生成会话ID时,会话劫持再次发生的可能性很小。

假设,用户的会话ID被复制,并且该用户在一段时间内没有工作或活动,并且没有请求使用旧的会话ID请求重新生成新的会话。 那么在会话id被劫持的情况下,黑客将使用该会话ID并向该服务器请求该ID,然后服务器将以重新生成的会话ID进行响应,以便黑客可以继续使用该服务。 实际的用户将不能再操作,因为他不知道什么是重新生成的ID,以及请求中会传递什么请求会话ID。 完全消失。

请纠正我,如果我错了某处。

会话劫持有很多标准的防御措施。 其中之一是将每个会话匹配到一个IP地址。

其他scheme可以使用从以下产生的HMAC:

  • 客户端IP的networking地址
  • 客户端发送的用户代理头
  • SID
  • 一个存储在服务器上的密钥

仅使用IP的networking地址的原因是用户在公共代理之后,在这种情况下,他们的IP地址可以随着每个请求而改变,但是networking地址保持不变。

当然,要真正安全起见,你真的应该对所有请求强制使用SSL,这样SID就不会被首先被攻击者拦截。 但并不是所有的网站都这样做( ::咳嗽:: Stack Overflow ::咳嗽::)

在我看来,当用户login时,可以将会话ID存储在数据库中,并在login之前检查每个人是否相同。删除用户注销时存储在数据库中的同一会话ID。 您可以轻松find每个用户的会话ID,否则我可以帮助您。

其中一个简单的实现可以通过在数据库中创build一个表来logging用户,然后在login时使用用户名和SID更新该表,这样可以防止其他login成为同一用户(现在在注销时)只需运行一个简单的查询,即删除数据库中login的数据,这也可以用来跟踪login用户在我们的网站一次。

显然,当您在浏览器中设置会话cookie时,该cookie将在请求中发送。 现在,当请求到来时,服务器将检查数据库中的会话ID并授予访问权限。 为了防止只有它重要的代理和IP存储,以便在检查服务器之前,确保会话访问授予唯一的客户端,而不是唯一的会话ID可以被劫持。

我不太了解编码部分。 所以我可以告诉你一个algorithm来做到这一点。 设置像SSL这样的东西,或设置会话cookie为安全,httpOnly将无法工作,如果用户嗅探局域网的会话ID(提供的用户和攻击者是在同一个局域网)。

因此,您可以做的是,一旦用户成功login到应用程序,就可以为Web应用程序的每个页面设置唯一的令牌,并在服务器端保留对此的跟踪。 因此,如果有效用户发送访问特定页面的请求,该页面的标记也将被发送到服务器端。 由于令牌对于特定会话的用户是唯一的,即使攻击者能够获得会话ID,他也不能劫持用户会话,因为他不能提供有效的令牌给服务器。

@Anandu M达斯:

我相信你可能指的是会话标记与每个会话标识的使用。 本网站可以解释会话使用的令牌:

https://blog.whitehatsec.com/tag/session-token/

虽然会话令牌很容易被XSS攻击所破坏,但这并不意味着它们不应该被使用。 我的意思是让我们面对现实,如果服务器上的安全漏洞可以破坏某个东西,那么这不是方法的错,它是介绍漏洞的程序员的错(突出Hesson和Rook的观点)。

如果遵循适当的安全约定和实践,并保护您的站点免受SQL注入,XSS,并要求通过HTTPSpipe理所有会话,则可以使用服务器端令牌轻松地pipe理CSRF的潜在攻击,这些令牌存储在会话中,并每次更新用户会导致他们的会话操作(如提交$ _POST)。 此外,无论将会话或其内容存储在url中,无论您认为自己的编码有多好。

当你的用户的安全是最重要的(应该是),会话令牌的使用将允许提供更好或更高级的function,而不损害其会话安全性。