如何保护cookie免受攻击

时间:2011-07-10 19:17:26

标签: asp.net security session cookies session-state

我想在会话期间使用cookie来存储userId,以避免不必要的往返数据库。此userId用于访问某些特定于用户的信息。由于cookie可以轻松编辑,我现在对安全问题很感兴趣。

为了禁止登录用户编辑他们的userId,以便访问其他用户的信息,我使用了一种非常简单的方法。我在userId cookie创建时添加了一个cookie,它存储了一个哈希值。在散列时,我使用硬编码的64字节密钥。从cookie中检索userId时,始终检查它是否与其散列值匹配。

这基本上是我的代码:

public static int GetUserId(Page page)
        {
            int userId;

            if (page.Request.Cookies["userId"] != null && page.Request.Cookies["userIdHashed"] != null)
            {
                string userIdHashed = page.Request.Cookies["userIdHashed"].Value;
                string userIdCoockie = page.Request.Cookies["userId"].Value;
                string coockie = (userIdCoockie + "945AFF2FD0F1D89B4B1DBEB1B0C5D3B8B5DCE000AAEA331EB0C3F3A68C3865EFA73BC6EBF30C8DF1AD6B9ECB7094DA5B0C1AF36B5BBD096E3D873E9589E3F664").GetHashCode().ToString();
                if (userIdHashed == coockie)
                {
                    userId = Int32.Parse(userIdCoockie);
                }
                else
                {
                    throw new Exception("UserId does not match!");
                }
            }

                else
                {

                    userId = ...//here userId is being retrieved from the data base and than:

                    page.Response.Cookies["userId"].Value = userId.ToString();
                    page.Response.Cookies["userId"].HttpOnly = true;
                string userIdHashed = (userId.ToString() + "945AFF2FD0F1D89B4B1DBEB1B0C5D3B8B5DCE000AAEA331EB0C3F3A68C3865EFA73BC6EBF30C8DF1AD6B9ECB7094DA5B0C1AF36B5BBD096E3D873E9589E3F664").GetHashCode().ToString();
                page.Response.Cookies["userIdHashed"].Value = userIdHashed;
                page.Response.Cookies["userIdHashed"].HttpOnly = true;
            }

            return userId;
        }

所以我的问题是:

  • 可以考虑采用这种方法 在这种情况下足够可靠吗?

  • 如果不是,我应该修改它以及如何或 我应该寻找不同的东西吗? (例如,通过加密/解密 System.Security.Cryptography为 建议here)?

还有一个问题:设置HttpCookie.HttpOnly = true以防止javascript访问cookie是否真的有意义,因为它也可以被用户轻松修改?

更新

非常感谢Kerrek SB和Darin Dimitrov的答案,他们认为考虑到已经建立了保护机制以保存这类信息,我自己尝试保护cookie是没有意义的。回传。

建议的选项是:

  • 使用ASP.NET cache(但我认为通常应该这样做 存储应该在用户之间共享的信息,所以我看一下 其他两个选项)。
  • 将带有userId的自定义字符串添加到的UserData部分 FormsAuthenticationTicket
  • 使用Session State

所以目前我正在决定后两者之间。

更改FormsAuthenticationTicket并不是很简单。此外,它不适用于无Cookie表单身份验证(如here所述)。

使用会话状态要容易得多,但它会影响性能,因为它会将值存储在服务器内存中。但是在我的情况下它可能不那么引人注目,因为我们只存储int类型的userId。

所以现在最后一个选项对我来说看起来好多了。但是,如果有其他人可以评论,支持或批评所讨论的任何选项,我将不胜感激。

提前致谢!

3 个答案:

答案 0 :(得分:3)

你似乎在这里重新发明了一些轮子。虽然在执行某些标准代码时可能可接受,但在涉及安全性时,这几乎总会导致灾难性后果。

要跟踪有效登录用户,我建议您使用forms authentication(此处是另一个useful tutorial)。它使用身份验证cookie来跟踪用户。这些cookie由框架安全加密,因此无法使用服务器<machineKey>文件的machine.config部分对其进行修改。

构建代码,只需访问当前登录的用户名即可:

public static string GetUserId(HttpContextBase context)
{
    if (context == null || !context.User.Identity.IsAuthenticated)
    {
        return null;
    }

    return context.User.Identity.Name;
}

你真的不应该手动处理所有这些东西,特别是当ASP.NET框架有一个内置的机制时。

答案 1 :(得分:2)

那非常迂回而且模糊不清。如果您已经有一个活动会话,为什么不在服务器端会话数据中存储这种数据(客户端从不需要知道,请注意)?

您真正需要与客户交换的所有内容都是会话ID。

答案 2 :(得分:0)

您还可以使用安全套接字层加密Cookie HttpCookie cookie = new HttpCookie(); cookie.Secure = true;