创建新的会话ID(无缝ID传输)

时间:2011-10-27 13:50:24

标签: c# asp.net .net session

因此,在登录/更改访问级别/等后,我遇到了一个实现会话ID滚动的有趣问题。

登录时我正在尝试使用SessionIDManager生成新的会话ID,但这只会更改cookie标头,它不会在HttpContext中换出会话,因此我向会话添加了其他详细信息(将用户绑定到会话ID的各种细节),他们立即迷路(更不用说旧会话被遗弃)。

为防止会话劫持(通过存储主要非SSL通信)和会话固定,我们应该在登录时生成新的会话ID,但Microsoft似乎不允许您这样做(grr,这么多读取 - 只有变量和没有构造函数的密封类)。我可以只迁移后端SQL中的所有数据,但这似乎有点“肮脏的黑客”。

有关如何正确执行此操作的任何想法?

编辑:

我发现的实施:

Session.Abandon();
Response.Cookies.Add(new HttpCookie("ASP.NET_SessionId", ""));

会话仍然是旧会话,因此在下一页上,所有更改都将丢失。

SessionIDManager在SaveSessionID之后不返回会话对象,因此我无法向刚创建的会话添加详细信息。在下一页加载我可以,但旧会话现在无法访问(并放弃,但即使它没有被放弃...)。

HttpContext.Session是只读的,即使它不是,HttpSessionState也没有构造函数。

编辑2:

Session Fixation in ASP.NET

显然会议固定和劫持在此之前已经讨论过了,答案是“微软似乎并不关心”,实施的两阶段修复效果不佳。

3 个答案:

答案 0 :(得分:1)

好吧,所以这是一个问题,展示了你如何使用这种方法劫持基于会话的auth和基于表单的身份验证(你需要一个有效的用户帐户,但你可以劫持其他人的会话),有一些在线博客抱怨会话固定和轻松利用劫持的能力。显然这是一个很大的问题。 Yahia指出Microsoft对fixing this不感兴趣。

我所做的是创建一个与会话ID配对的真实性密钥,登录后我们会生成一个新的并将其放入会话中,如果会话中有密钥,则为用户提供cookie他们必须匹配,如果不是,我们会踢用户(劫持企图)。这似乎是在所提到的博客上执行此操作的常用方法(另一种方法是使用表单auth来基本上加密cookie,而这很好,我希望该解决方案与多种类型的身份验证兼容)。


根据Yahia的建议,建议可以帮助防止任何非ssl通信使用另一个应用程序作为非ssl前端,只提供302重定向,这有助于吨通过首先防止会话ID的泄露,需要对应用程序的部署方式进行大量重组以进行修复,而IMO:.NET的iffy会话管理应该首先修复,我想要我们的应用程序从头开始完全保护,不依赖于其他应用程序进行302重定向,以便任何信息泄漏都无关紧要,因为cookie将在登录时轮换。

答案 1 :(得分:0)

您是否看过FormsAuthentication.SetAuthCookie方法?

尝试这样的事情:

FormsAuthentication.SignOut();
HttpContext.Current.Session.Abandon();
FormsAuthentication.SetAuthCookie(newCode, true);

我希望这对你有帮助....

答案 2 :(得分:0)

我的回答有点晚了,但我一直在寻找相同的东西所以我认为我应该发布我发现的东西......而不是使用SessionIdManager重置cookie,它似乎是一个更好的“钩子”将是安装自定义会话ID管理器:

<sessionState mode="InProc" ... 
              sessionIDManagerType="MyAssembly.SessionFixationIdManager, MyAssembly" />

然后,我使用现有的SessionIdManager实现了我的ISessionIdManager。例如:

class SessionFixationIdManager : ISessionIDManager
{
    private SessionIDManager _originalManager = new SessionIDManager();

    public string CreateSessionID(System.Web.HttpContext context)
    {
        // Default process for creating session IDs is fine...
        return _originalManager.CreateSessionID(context);
    }

    etc.
}

我唯一不同的方法是GetSessionID方法 - 如果请求未经过身份验证,则忽略传入的Cookie并发出新的:

public string GetSessionID(System.Web.HttpContext context)
{
    // Never use a session ID from an unauthenticated request...
    if (!context.Request.IsAuthenticated) 
        return null;

    return _originalManager.GetSessionID(context);
}

通过这样做,似乎可以保证:

  1. 会话ID cookie将在对用户进行身份验证的响应中重新发布。我正在使用表单身份验证,因此这是发布表单身份验证Cookie的响应。

  2. 我实际上可以在我对用户进行身份验证的请求中使用会话 - 因为会话ID被重新分配之前会话已分配给上下文请求。

  3. 现在,这只是安全方面努力的开始。例如,我仍然需要做一些事情来将会话绑定到经过身份验证的用户(例如,将某些会话值加密到表单身份验证cookie中)。这意味着我无法在登录过程中使用会话状态(它必须全部作为单个请求处理,或使用ViewState等)。

    但我认为这可以保证未经身份验证的用户无法执行会话固定。

    (老实说,我不确定这是否值得。在每个请求上针对会话验证表单身份验证数据(或其他一些真实性密钥)可能提供相同级别的安全性,而无需跳过这些额外的箍但是,实施安全最佳实践是一个目标,我认为这样做可以在没有错误的两阶段解决方案的情况下失去初始请求的所有上下文......)