将数据放入cookie中是否安全?

我正在使用asp.net mvc 2.0,我想知道将信息放入cookie有多安全?

就像我在我的cookie中放入一个加密的表单身份validation票据,这样我可以将那些可能敏感的信息放在那里吗?

string encryptedTicket = FormsAuthentication.Encrypt(authTicket) HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); 

就像我没有存储密码或类似的东西,但我想存储UserId,因为目前每次用户向我的网站发出请求时,我必须进行查询并获取用户Userid,因为我的数据库中的每个表都需要你使用userId获取正确的行。

所以这些开始快速加起来所以我宁愿拥有它,如果用户被认证一次,那就是它,直到他们需要再次重新认证。 如果我将存储此userId,我可以将如此多的请求保存到数据库。

然而,我不希望它以明文forms出现,因为潜在的人可能会使用它来尝试从数据库中获取一行,而实际上它们不应该存在。

显示身份validation使用的加密有多好?

除了cookie加密,您还应该实现旋转令牌以防止重放攻击。

这个想法是加密的cookie包含一些值,可以与服务器上的已知值进行比较。 如果数据匹配,则请求成功。 如果数据不匹配,那么您正在经历重播攻击并需要终止会话。

UPDATE
其中一条评论询问我是否打算将值存储在cookie中。 答案是肯定的。 整个cookie应该加密,可以通过使用HttpModule自动完成。 加密 cookie内部是您的任何常规信息+更改令牌。

在每个post上,检查令牌。 如果它有效,则允许事务,创建新的随机令牌,存储在cookie中,然后将其发送回浏览器。 再次,以加密forms。

结果是你的cookie是安全的(你正在使用3DES?),任何攻击者都有极其有限的机会甚至可以尝试重放攻击。 如果令牌未通过集合,您可以简单地发出警报并采取适当措施。

所有需要的服务器端都是跟踪用户及其当前令牌。 这通常是一个小得多的数据库命中,而不是在每个页面加载时查找诸如用户名之类的小东西。

更新2
我一直试图弄清楚这是否比保持会话中存储的更改值更好或更差。 我得出的结论是,在Web服务器上存储会话中的旋转值对于防止重放攻击绝对没有任何作用,因此比将该值放入cookie中更不安全。

考虑这种情况。 浏览器发出请求。 服务器查看会话ID并提取会话对象,然后执行工作,并将响应发送回浏览器。 与此同时,BlackHat Bob记录了这笔交易。

Bob然后将完全相同的请求(包括会话ID)发送到服务器。 此时,服务器完全没有办法知道这是来自攻击者的请求。 您不能使用IP,因为代理使用可能会更改,您无法使用浏览器指纹识别,因为所有这些信息都会记录在初始交换中。 此外,鉴于会话通常至少有30分钟,有时甚至更长,攻击者有一个非常好的窗口可以工作。

因此,无论如何,为了防止重放,您必须在每次请求后向浏览器发送更改令牌。

现在,这给我们留下了一个问题,即是否还将用户ID等值存储在加密cookie中,或者将其存储在会话变量中。 对于会话,您会担心诸如更高的内存和CPU利用率以及负载平衡等潜在问题。对于Cookie,您有一些小于4kb的数据,并且在1kb或更小的范围内正确完成对每个请求。 我想这将归结为你是否愿意添加更多/更大的服务器和内部网络设备来处理请求(会话)或支付更大的互联网管道(cookie)。

加密足够好,这不是薄弱环节。

弱链接是cookie值可能被截获,而其他人可能会冒充用户。

因此,cookie中的信息足够安全,但您无法保护cookie本身。

你问题的标题与你提出的问题并不完全一致。 你在这里问两件事。

1.有没有一种安全的方式将数据存储在cookie中?

答案是肯定的。 要在cookie中安全地存储数据,您必须加密要存储的数据,然后对加密数据进行签名。 加密它可以防止攻击者读取数据,对其进行签名可以防止攻击者修改数据。 这将确保数据的完整性。 您可以使用此方法存储有关您要保密的用户的数据(他们的电子邮件地址,出生日期等)。 注意:在cookie中安全存储数据不是validation用户身份的安全方法! 如果您将用户的用户ID存储在已签名和加密的cookie中,则不会阻止攻击者窃取整个cookie并将其发送回服务器。 无法知道身份validationcookie是否来自用户输入其用户名和密码的同一浏览器。 这引出了我们第二个问题(你实际问的那个)……

2.是否有一种安全的方法来使用cookievalidation用户?

是。 要安全地validation用户身份,您必须将问题1中的技术与SSL(https)结合使用。 SSL确保只有浏览器才能访问身份validationcookie(带有用户ID的签名加密cookie)。 这意味着您的登录过程(接受用户名和密码,以及设置身份validationcookie)必须通过SSL进行。 在服务器上设置身份validationcookie时,还必须将HttpCookie.Secure属性设置为true。 这告诉浏览器在通过SSL向您的网站发出请求时仅包含此cookie。 您还应该在加密的身份validationcookie中包含过期时间,以防止有人在图书馆时忘记退出您的网站。 此方法的一个副作用是,只有您网站上的SSL页面才能validation用户身份。 这提出了第三个问题……

3.如何在不使用SSL的情况下安全地对用户进行身份validation?

你没有。 但你确实有选择。 一种策略是在登录时创建两个auth cookie,一个常规cookie和一个仅ssl-only(加密和签名)。 代表用户执行敏感操作时,要求页面为SSL并使用仅SSL cookie。 在进行非敏感操作(例如浏览基于其帐户所在国家/地区定制的商店)时,您可以使用常规身份validationCookie。 另一种选择是拆分页面,以便通过AJAX或json检索需要知道用户是谁的信息异步。 例如:您通过http返回博客的整个页面,然后您发出SSL AJAX请求以获取当前用户名,电子邮件,个人资料图片等。我们在我工作的网站上使用这两种技术。

我知道这个问题差不多一年前被问过。 为了后人的缘故,我正在写这篇文章。 🙂

正如您所说,在cookie中存储任何数据的一个好方法是加密数据。 在放入cookie之前加密,并在读取之后解密。

在存储用户标识符的示例中,选择不太可能针对您的系统使用的内容。 对于用户标识,使用guid而不是数据库表上PK的可能递增整数 。 在攻击您的系统期间,guid不会轻易更改为成功猜测其他用户。

一旦识别或validation了用户,请继续并在Session存储用户对象或密钥属性。

在具有理想密码的理想世界中,这不是问题。 不幸的是,在现实世界中没有什么是理想的,也永远不会有理想的密码。 安全就是解决这些现实世界的威胁。 密码系统总是容易受到攻击,它可能是一种微不足道的(暴力)攻击,也可能是它自身原始的一个缺陷。 更进一步,你很可能会破坏原语的实现,常见的错误包括非随机或空IV,密钥管理和不正确的分组密码模式。

简而言之, 这是对密码术的严重滥用。 通过使用会话变量避免一起解决这个问题是最好的。 这就是会话存在的原因,重点是将浏览器链接到存储在服务器上的状态数据。

编辑:加密cookie导致ASP.NET oracle填充攻击 。 应该通过使用Cryptographic Nonce一起避免这种情况。 就像我说的,这是对密码学的严重误用。

对于您的特定场景(用户ID),简短的答案是否定的

对于长期答案,想象一下这个假设情景:

  1. 您导航到stackoverflow.com;
  2. 填写您的用户名/密码并提交表格;
  3. 服务器会向您发送一个包含您的用户ID的cookie,该cookie将用于在下次请求时识别您;
  4. 由于你的连接不安全(HTTPS),一个坏人嗅了它,并抓住了cookie。
  5. 坏人可以访问您的帐户,因为服务器没有存储,比方说,您的IP地址,因此,无法区分您的机器和坏人。

仍然在这种情况下,假设服务器存储了您的IP地址,但您在公司LAN上,并且您的外部IP与另外100台机器相同。 想象一下,有权访问其中一台机器的人复制了你的cookie。 你已经知道了,对吗? 🙂

我的建议是: 将敏感信息放在HTTP会话上

更新:有一个会话意味着一个cookie(或至少一个丑陋的URL),从而导致我们回到同样的问题:它可以被捕获。 避免这种情况的唯一方法是添加端到端加密:HTTP + SSL = HTTPS 。 如果有人说“哦,但cookies/会话应该足以阻止大多数人”,请查看Firesheep

从安全的角度来看,这没关系 (不是很好,但没有 )。 然而,从性能的角度来看,这是你想要避免的。

每次请求时,所有cookie都从客户端传输到服务器。 如今大多数用户可能拥有快速宽带连接,但这些连接是不对称的 – 用于传输cookie数据的上游带宽通常仍然非常有限。 如果您在Cookie中放入了太多信息,即使您的网络服务器具有备用容量,您的网站也会显得迟钝。 它还可以提高您的带宽费用。 这些是您的测试中不会出现的点,这些点很可能发生在您的公司网络上,从客户端到服务器的上游带宽很多。

更好(通用)的方法是在cookie中保留一个单独的标记,用作数据库查找信息的关键字。 数据库调用也相对较慢(与已经在内存中或请求中的信息相比),但是这样的主键查找并不坏,而且在将数据发送到世界各地的四分之一的情况下仍然更好。请求。 这对于安全性来说也更好,因为它可以尽可能地将数据保留在用户的机器上并远离线路。 此标记不应该类似于您的问题中的用户标识,而是更短暂的标记 – 用于索引和隐藏更大数据块的密钥,您的用户标识可能是其中的一部分。

对于您的userID(可能只有一个整数)以及其他重要的数据,请将其保留在Web服务器的内存中。 把它放在会话中。

您正在查看的用途是能够在Forms Auth Ticket中存储信息的确切目的。

没有。在Padding oracle攻击中已经certificate,由于错误泄漏,接收加密数据(CBC)可能是危险的。

我绝对不是加密专家,但我最近看到了一个使用此攻击解密加密视图状态的演示。

加密cookie中的userid值只会阻止用户知道值是什么。 它不是

  • 防止cookie重放(使用SSL防止攻击者拦截受害者的cookie)
  • 防止篡改(攻击者仍然可以盲目地翻转编码cookie中的位,并有可能将其解码为有效的用户ID,使用HMAC来防止这种情况)
  • 完全阻止用户获取解密值(用户可以强行离线,使用强加密密钥使成功的可能性降低)

加密cookie还会引入密钥管理问题。 例如,当您旋转加密密钥时,您必须确保使用旧密钥的“实时”会话不会立即失败。 您考虑过管理加密密钥,对吗? 管理员离开后会发生什么? 它受到了损害? 等等

您的体系结构(负载平衡器,服务器分发等)是否排除使用服务器端会话对象来跟踪此信息? 如果没有,将userid绑定到会话对象并在服务器上保留“敏感”数据 – 用户只需要有一个会话cookie。

对于您所陈述的问题,会话对象可能会更容易,更安全。

为了确保正确的auth cookie保护,您应该确保通过设置machineKey validation =“SHA1”属性来指定安全加密/散列方案(通常在web.config中)(我使用SHA1,但您可以用不同的替换它)如果需要,提供者)。 然后,确保您的表单身份validation设置了protect =“All”属性,以便对cookie进行哈希和加密。 所有在一个:)不可否认和数据安全:)

ASP.NET将处理加密/解密[编辑: 只有auth cookie! 为你的cookie,虽然对于自定义cookie你可以使用FormsAuthentication.Encrypt(…)方法,所以只要确保你没有通过查询字符串之类的其他明文方式发送UserId。

 HttpCookie c; c.Secure = true; 

显然这仅在通过SSL传输时有效,但此设置告诉浏览器除非连接是SSL,否则不发送cookie,从而防止通过中间人攻击进行拦截。 如果您没有使用安全连接,那么被动嗅探连接的任何人都可以完全看到cookie中的数据。 考虑到公共wifi的普及,顺便提一下,这并不像你想象的那么小。

要解决的第一件事是所涉及的连接是否安全。 如果不是,则假设您和客户之间的cookie或其他任何内容将被截获。

一旦cookie在客户机上,它就是一种责任。 审查cookie盗窃,跨站点请求伪造,混淆副问题。

Cookie限制:大小,可能被禁用和安全风险(篡改)。 当然,如果你加密cookie,可能会有性能损失。 Session和Viewstate将是不错的选择。 如果您希望将其存储在客户端,则viewstate会更好。 您可以加密字符串userid并存储在viewstate中。 会议将是最佳选择。 如果数据库调用很慢,请考虑缓存

视图状态