防止会话劫持



如何防止多个客户端使用同一会话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的多个请求来保护会话不被劫持是非常荒谬的,并且会破坏会话的整个目的。

不幸的是,没有有效的方法可以明确地识别来自攻击者的请求,而不是真正的请求。因为大多数计数器检查的属性,如IP地址或用户代理特征,要么不可靠(IP地址可能在多个请求中更改),要么很容易伪造(例如用户代理请求标头),因此可能会产生不必要的误报(即真正的用户交换IP地址)或误报(也就是说,攻击者能够使用相同的用户代理成功伪造请求)。

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

也就是说,你应该:

  • 使用足够的随机输入生成会话ID(请参阅session.entropy_filesession.entrpy_length会话.hash_function
  • 在传输过程中使用HTTPS保护会话ID
  • 将会话ID存储在cookie中,而不是URL中,以避免通过Referer泄漏(请参阅session.use_only_cookies
  • 将具有HttpOnlySecure属性的cookie设置为禁止通过JavaScript访问(在XSS漏洞的情况下)和禁止通过不安全通道传输(请参阅session.cokie_httponlysession.cokie_secure

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

我们能做这样的事情吗。

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

可以通过为会话创建公共函数或类来实现此funda,以便在处理每个请求之前对其进行验证。这几乎不需要几微秒。但是,如果许多用户正在访问您的网站,而您拥有庞大的会话数据库,那么这可能是一个小性能问题。但是,与其他方法相比,它肯定是非常安全的=>使用重新生成会话。

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

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

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

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

其他方案可能使用由生成的HMAC

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

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

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

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

  • 网络窃听
  • 无意暴露
  • 转发、代理和网络钓鱼
  • 反向代理

始终建议使用SSL安全套接字层
在脚本开始时,还可以使用cookie来遵循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
?>

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

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

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

我对编码部分不太了解。所以我可以告诉你一个算法来做这件事。如果用户从LAN网络中窃取会话id(前提是用户和攻击者在同一LAN中),则设置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中,无论你认为它们的编码有多好。

当用户的安全性至关重要时(应该如此),会话令牌的使用将允许在不损害其会话安全的情况下提供更好或更高级的功能。

最新更新