75

How do you prevent multiple clients from using the same session ID? I'm asking this because I want to add an extra layer of security to prevent session hijacking on my website. If a hacker somehow figures out another user's session ID and makes requests with that SID, how can I detect that there are different clients sharing a single SID on the server and then reject the hijack attempt?

EDIT

I have accepted Gumbo's answer after careful consideration because I've come to the realization that what I'm asking for is impossible due to the restrictions of a stateless HTTP protocol. I forgot about what is perhaps the most fundamental principle of HTTP, and now that I think about this question seems a bit trivial.

Let me elaborate what I mean:

After User A logs in on example.com, he is given some random session ID, for simplicity's sake, let it be 'abc123'. This session ID is stored as a cookie on the client side and is validated with a server-side session to ensure the user who logged in remains logged in as he moves from one webpage to another. This cookie of course would not need to exist if HTTP were not stateless. For that reason, if User B steals User A's SID, and creates a cookie on his computer with the value 'abc123', he would have successfully hijacked User A's session, but there is simply no way for the server to legitimately recognize that User B's request is any different from User A's requests, and therefore the server has no reason to reject any request. Even if we were to list the sessions that were already active on the server and try to see if someone is accessing a session that is already active, how can we determine that it is another user who is accessing the session illegitimately and not the same user who is already logged in with a session ID, but simply trying to make another request with it (ie navigate to a different webpage). We can't. Checking the user agent? Can be spoofed - but good as a Defense in Depth measure nevertheless. IP Address? Can change for legitimate reasons - but instead of not checking for the IP address at all, I suggest checking something like the first two octets of the IP, as even a user on a data plan network who constantly has a changing IP for perfectly legitimate reasons would only usually have the last two octets of their IP change.

In consclusion, it is the stateless HTTP that condemns us to never being able to fully protect our websites from session hijacking, but good practices (like the ones Gumbo has provided) will be good enough to prevent a good majority of session attacks. Trying to protect sessions from hijacking by denying multiple requests of the same SID is therefore simply ludicrous, and would defeat the whole purpose of sessions.

4

9 回答 9

91

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

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

也就是说,您应该:

除此之外,您还应该重新生成会话 ID,同时在某些会话状态更改(例如登录后确认真实性或更改授权/权限)后使旧 ID 无效(请参阅session_regenerate_id函数),您还可以定期执行此操作以减少时间跨度成功的会话劫持攻击。

于 2012-09-02T08:45:42.353 回答
5

我们能不能做这样的事情。

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

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

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

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

如果我在某个地方错了,请纠正我。

于 2014-06-17T14:13:34.857 回答
4

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

其他方案可能会使用从以下位置生成的 HMAC:

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

仅使用 IP 的网络地址的原因是,如果用户位于公共代理后面,在这种情况下,他们的 IP 地址可以随每个请求而更改,但网络地址保持不变。

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

于 2012-09-02T07:42:37.467 回答
3

会话劫持是一个严重的威胁,它必须通过使用安全套接字层来处理涉及事务的高级应用程序或使用简单的技术,如使用 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
?>
于 2019-04-17T21:53:25.940 回答
1

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

于 2012-09-02T04:45:00.353 回答
1

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

于 2014-06-18T07:44:54.627 回答
1

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

于 2012-09-02T04:41:47.577 回答
0

I don't know about the coding part well. So I can tell u an algorithm to do this. Setting stuffs like SSL, or setting the session cookie to secure and httpOnly wont work if a user sniffs the session id from a LAN network(Provided user and attacker are in the same LAN).

So what you can do is, once the user successfully logs into the application, set unique token to each and every pages of the web application and keep a track of this at the server side. So that if the valid user sends the request to access a particular page, the token of that page will also be sent to the server side. Since the tokens are unique for a user for a particular session, even if the attacker can get the session id, he cannot hijack the users session as he cannot provide the valid token to the server.

于 2014-10-16T13:26:15.333 回答
0

@阿南杜 M 达斯:

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

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

尽管会话令牌很容易受到 XSS 攻击的破坏,但这并不意味着它们永远不应该被使用。我的意思是让我们面对现实,如果服务器上的安全漏洞会损害某些东西,那不是方法的错,而是引入该漏洞的程序员的错(强调 Hesson 和 Rook 提出的观点)。

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

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

于 2015-09-26T22:42:34.330 回答