预防会话劫持

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

剪辑

经过慎重考虑,我接受了 Gumbo 的回答,因为我已经意识到,由于 无状态的 HTTP 协议的限制,我所要求的是不可能的。我忘记了 HTTP 最基本的原则是什么,现在考虑这个问题似乎有点琐碎。

让我详细解释一下我的意思:

在用户 A 登录 example.com 之后,他会得到一个随机的会话 ID,为了简单起见,让它为‘ abc123’。此会话 ID 在客户端存储为 cookie,并通过服务器端会话进行验证,以确保登录的用户在从一个网页移动到另一个网页时仍然登录。如果 HTTP 不是无状态的,那么这个 cookie 当然不需要存在。出于这个原因,如果用户 B 窃取用户 A 的 SID,并在他的计算机上创建一个值为“ abc123”的 cookie,他将成功劫持用户 A 的会话,但是服务器根本没有办法合法地认识到用户 B 的请求与用户 A 的请求有任何不同,因此服务器没有理由拒绝任何请求。即使我们列出服务器上已经激活的会话,并试图查看是否有人正在访问已经激活的会话,我们如何确定是另一个用户非法访问会话,而不是同一个用户已经用会话 ID 登录,但只是试图使用它发出另一个请求(即导航到一个不同的网页)。我们不能。在查用户代理吗?可以被欺骗-但是作为一个深度防御措施仍然很好。IP 地址?可以由于合法的原因而改变——但是与其完全不检查 IP 地址,我建议检查一些类似于 IP 的前两个八位元的东西,因为即使是在数据计划网络上的用户,如果他们由于完全合法的原因不断地改变 IP,通常也只会改变他们 IP 的最后两个八位元。

总之,是无状态的 HTTP 让我们无法完全保护我们的网站免受会话劫持攻击,但是良好的实践(就像 Gumbo 提供的那些)足以防止大多数会话攻击。因此,试图通过拒绝同一 SID 的多个请求来保护会话免遭劫持的做法简直是荒谬可笑的,而且会破坏会话的整个目的。

45798 次浏览

在我看来,当用户登录时,您可以在数据库中存储会话 ID,并在登录前检查每个人的会话 ID。当用户注销时,删除存储在数据库中的相同会话 ID。您可以很容易地找到每个用户的会话 ID,否则我可以帮助您。

其中一个简单的实现就是在数据库中创建一个表,作为已登录的用户,然后在登录时,用用户名和他的 SID 更新这个表,这将防止其他用户作为同一个用户登录,现在在注销时,只需运行一个简单的查询,删除数据库中已登录的数据,这也可以用来跟踪一次登录在你的网站上的用户。

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

其他方案 可以使用由以下方面产生的 HMAC:

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

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

当然,为了真正的安全,您确实应该对所有请求强制使用 SSL,这样 SID 就不会被潜在的攻击者拦截。但并非所有的网站都这样做(Stack Overflow 咳嗽:)。

不幸的是,没有有效的方法可以明确地识别来自攻击者而非真正请求的请求。因为大多数反措施检查的属性,如 IP 地址或用户代理特征,要么不可靠(IP 地址可能在多个请求之间变化)或可以很容易伪造(如 用户代理请求头) ,因此可以产生不必要的假阳性(即真正的用户交换 IP 地址)或假阴性(即攻击者能够成功伪造请求与同一 用户代理)。

这就是为什么防止会话劫持攻击的最好方法是确保攻击者无法找到其他用户的会话 ID。这意味着你应该设计你的应用程序和它的会话管理,(1)攻击者不能通过使用足够的熵来猜测一个有效的会话 ID,(2)攻击者没有其他方法通过已知的攻击/漏洞来获得一个有效的会话 ID,比如嗅探网络通信、跨网站脚本、通过 推荐人泄漏等。

也就是说,你应该:

除此之外,你还应该在某些会话状态改变后重新生成会话 ID,同时使旧的会话 ID 失效(见 session_regenerate_id功能)(例如,在登录后确认真实性或更改授权/特权) ,你还可以定期这样做,以减少成功的会话劫持攻击的时间跨度。

我们能做这样的事吗。

在数据库中存储会话 ID。 还要存储这个会话 ID 的 Ip 地址和 HTTP _ USER _ AGENT。 现在,当一个请求到达包含匹配会话 ID 的服务器时,在脚本中检查来自哪个代理和 ip。

可以通过为会话创建公共函数或类来使这个基金会工作,以便在处理每个请求之前进行验证。几秒钟就能搞定。但是,如果有许多用户访问您的站点,并且您有大量的会话数据库,那么这可能是一个小的性能问题。但是,与其他方法相比,它肯定是非常安全的 = > 使用重新生成会话。

在重新生成会话 id 的过程中,再次出现会话劫持的可能性也很小。

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

如果我哪里说错了,请纠正我。

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

我不太了解编程这部分。我可以告诉你一个算法。如果用户从局域网中嗅探会话 ID (假设用户和攻击者在同一个局域网中) ,那么设置 SSL 之类的东西,或者将会话 cookie 设置为安全且 httpOnly 不起作用。

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

@ Anandu M Das:

我相信您可能指的是对每个会话 ID 使用会话令牌。这个网站可以解释会话令牌的使用:

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

尽管会话令牌很容易受到 XSS 攻击的破坏,但这并不意味着永远不应该使用它们。我的意思是,让我们面对它,如果某些东西是由于服务器上的安全漏洞造成的,这不是方法的错误,而是引入这个漏洞的程序员的错误(为了突出 Hesson 和 Rook 提出的要点)。

如果您遵循适当的安全约定和实践,并保护您的站点不受 SQL 注入、 XSS 和要求通过 HTTPS 管理所有会话的影响,那么您可以通过使用服务器端令牌(存储在会话中)轻松管理来自 CSRF 的潜在攻击,并在用户对其会话进行操作时进行更新(比如提交 $_ POST)。另外,永远不要将会话或其内容存储在 URL 中,无论您认为它们是如何编码的。

当您的用户的安全性至关重要(这是应该的)时,使用会话令牌将允许提供更好或更高级的功能,而不会损害其会话安全性。

会话劫持是一个严重的威胁,它必须为涉及事务的高级应用程序使用安全套接字层,或使用上文所述的使用 cookies、会话超时和重新生成 id 等简单技术来处理。
当互联网诞生时,HTTP 通信被设计为无状态的; 也就是说,两个实体之间的连接只存在于请求发送到服务器所需的短暂时间内,并且最终的响应传回客户端。 下面是黑客劫持会话的一些方法

  • 网络窃听
  • 不知情的暴露
  • 转发、代理和网络钓鱼
  • 反向代理

始终推荐 SSL 传输层安全
还可以在脚本开始处使用 饼干来执行 ini _ set ()指令,以覆盖 php.ini 中的任何全局设置:

ini_set( 'session.use_only_cookies', TRUE );
ini_set( 'session.use_trans_sid', FALSE );

使用 会话超时和会话重新生成 ID

<?php
// regenerate session on successful login
if ( !empty( $_POST['password'] ) && $_POST['password'] === $password )
{
// if authenticated, generate a new random session ID
session_regenerate_id();


// set session to authenticated
$_SESSION['auth'] = TRUE;


// redirect to make the new session ID live


header( 'Location: ' . $_SERVER['SCRIPT_NAME'] );
}
// take some action
?>