会话修复 - 在asp.net core 2

时间:2017-11-16 17:05:16

标签: session asp.net-core

根据我的理解,我们有

  1. sessionId存储在Cookie .AspNetCore.Session
  2. 删除Cookie并清除会话无效。

    context.HttpContext.Session.Clear();
    foreach (var cookie in context.HttpContext.Request.Cookies.Keys)
    {
         context.HttpContext.Response.Cookies.Delete(cookie);
    }
    
  3. 所以问题是我们可以以某种方式更改sessionId,还是有办法保护我们免受会话修复的影响?

2 个答案:

答案 0 :(得分:1)

Session.Clear仅从会话中删除所有数据,实际上并不删除会话本身。当超时被击中时会发生这种情况。在我看来,这是一个奇怪的选择,因为ASP.NET核心团队没有像以前那样实现Session.Abandon,因为实际上删除实际的会话本身。 / p>

只要实际会话仍然存在,即使它的数据不再存在,它仍然可以通过该会话ID检索,结果,问题转移到客户端。

重要的是,服务器实际上无法让客户端做任何事情。调用Cookies.Delete实际上只会为同一个Cookie发送一个新的Set-Cookie响应标头,其中包含过去的过期日期。此应该提示客户端(浏览器,最有可能)然后删除该cookie,因为它现在已过期。但是,这在客户端完全是100%,因此如果有错误或客户端没有接受更改或客户端因任何原因拒绝遵守,则cookie将保留。然后,再次,如果cookie仍然存在并且由它包含的会话ID标识的会话仍然存在,则可以恢复它。

长短,你的代码应该工作,除了你已经 之外别无他法这样做。如果会话没有被放弃,那么某处会出现其他问题(最有可能是客户端)。

答案 1 :(得分:1)

...或者有什么方法可以保护我们免受会话固定?

是的! OWASP声明:

不幸的是,某些平台(尤其是Microsoft ASP)不会为sessionid cookie生成新值,而只是将现有值与新会话相关联。这样可以保证几乎所有的ASP应用程序都容易受到会话修复的攻击,除非它们已采取具体措施加以保护。

同一页上推荐了一种ASP.Net的方法,我们将其用于所有ASP.Net应用程序并通过了笔测试。我认为对于ASP.Net Core仍然有效:

这个想法是,由于ASP禁止对ASPSESSIONIDxxxxx cookie的写访问,并且不允许我们以任何方式对其进行更改,因此我们必须使用一个我们可以控制的其他cookie来检测任何篡改。因此,我们将用户浏览器中的Cookie设置为随机值,并将会话变量设置为相同值。如果会话变量和Cookie值不匹配,则说明我们存在潜在的固定攻击,应该使该会话无效,并迫使用户再次登录。

这是我们如何在.Net Core Razor Pages中进行此处理的简化示例,应使您了解如何自己实现它:

public IActionResult OnPost()
{
    Login();

    return Redirect("~/Login");
}

private void Login()
{
    // Check the user's credentials and do all the other necessary stuff.
    // ... 

    // Create the random value we will use to secure the session.
    string authId = GenerateAuthId();

    // Store the value in both our Session and a Cookie.
    HttpContext.Session.SetString("AuthId", authId);
    CookieOptions options = new CookieOptions()
    {
        Path = "/",
        HttpOnly = true,
        Secure = true,
        SameSite = Strict
    };
    Response.Cookies.Append("AuthCookie", authId, options);
}

private string GenerateAuthId()
{
    using(RandomNumberGenerator rng = new RNGCryptoServiceProvider())
    {
        byte[] tokenData = new byte[32];
        rng.GetBytes(tokenData);
        return Convert.ToBase64String(tokenData);
    }
}

在需要的地方检查会话和Cookie的内容。如果它们不匹配,则应该Clear会话(我认为Session.Abandon在.Net Core中仍然不可用)并注销用户。

public void OnGet()
{
    string cookieValue = Request.Cookies["AuthCookie"];
    string sessionValue = HttpContext.Session.GetString("AuthId");

    if (cookieValue == null || sessionValue == null || cookieValue != sessionValue )
    {
        // Invalidate the session and log out the current user.
    }
}