【问题标题】:Signed session cookies. A good idea?签名的会话 cookie。一个好主意?
【发布时间】:2011-03-15 11:47:42
【问题描述】:

为了提高性能,我想尝试消除一个普通的“会话 cookie”,但加密 cookie 本身中的所有信息。

一个非常简单的例子:

userid= 12345
time=now()
signature = hmac('SHA1',userid + ":" + time, secret);

cookie = userid + ':' + time + ':' + signature;

该时间将用于最长到期时间,因此 cookie 不会永远存在。

现在有个大问题:这是个坏主意吗?

我最好改用 AES256 吗?就我而言,数据不是机密的,但在任何情况下都不得更改。

编辑

经过一些很好的评论和cmets,我想补充一下:

  • “秘密”对于每个用户都是唯一的且不可预测(随机字符串 + 用户 ID?)
  • cookie 将自动过期(这是根据时间值 + 一定的秒数完成的)。
  • 如果用户更改密码(或者甚至注销?)密码应该会更改。

最后一点:我正在尝试提出减少数据库负载的解决方案。这只是我正在研究的解决方案之一,但它是我最喜欢的。主要原因是我不必研究更适合这种数据的其他存储机制(memcache、nosql),它使 Web 应用程序更加“无状态”。

10 年后编辑

JWT 现在是一件事。

【问题讨论】:

  • 嗨,米粉饼干,它是 PHP,但为了避免针对特定平台的讨论,我将其省略了。目前我们在多个网络服务器上使用 PHP,以及 Master-Master mysql 设置。会话 cookie 缓存在 memcached 中。我们的瓶颈主要是添加和删除 cookie。复制还需要转到辅助数据中心,与会话相关的查询占流量的很大一部分。
  • “秘密”对于每个用户来说都是唯一的且不可预测(随机字符串 + 用户 ID ?)
  • 同样的事情@如果用户更改了他们的密码,(或者甚至可能注销?)秘密应该改变。
  • 这是一个老问题,但这种使用签名 cookie 的方法现在已成为主流。 python 框架 Flask 将其用于其会话 (flask.pocoo.org/docs/dev/api/#sessions)。尽管单个密钥通常在应用程序范围内使用,而不是每个用户的密钥。
  • @cake 也是这么想的,他还是存储了状态。

标签: security cookies


【解决方案1】:

签名令牌对于您想要颁发令牌的任何事情都是一种很好的方法,然后在返回令牌时,能够验证您是否颁发了令牌,而无需在服务器端存储任何数据。这适用于以下功能:

  • 限时账户登录;
  • 密码重置;
  • 抗 XSRF 形式;
  • 限时表单提交(反垃圾邮件)。

它本身并不能替代会话 cookie,但如果它可以完全消除对任何会话存储的需求,那可能是一件好事,即使性能差异不会很大。

HMAC 是生成签名令牌的一种合理方式。它不会是最快的。如果您知道并且可以避免扩展攻击,您可能能够摆脱简单的哈希。我会让你决定这是否值得你冒险。

我假设 hmac() 在您使用的任何语言中都已设置为使用合适的服务器端密钥,否则您将无法获得安全的签名令牌。如果您要围绕它建立整个身份验证系统,这个秘密必须是强大且受到良好保护的。如果您必须更改它,每个人都会退出。

出于登录和密码重置的目的,您可能需要在令牌中添加一个额外的因素,即密码生成编号。如果愿意,您可以为此重新使用数据库中散列密码的盐值。这个想法是,当用户更改密码时,它应该使任何已发布的令牌无效(除了浏览器上的 cookie 进行密码更改,它会被重新发布的令牌替换)。否则,发现其帐户已被盗用的用户无法锁定其他方。

【讨论】:

  • 阅读这方面的内容似乎是个好主意;将 cookie 标记为安全,设置过期时间,将其绑定到您网站的某个区域(例如,没有用户帐户更改命令)。还将用户代理字符串和 IP 地址散列到密钥中,这样 cookie 就不会被盗。请注意小于 4k 的 cookie 最大大小限制。有很多问题,我认为寻找更快的服务器端会话 impl(riak,memcached)比冒着安全漏洞风险更明智。
  • @simbo1905 - 感谢您对必须正确处理的细节进行了出色的总结。关于“这么多陷阱” - 还有比你提到的更多的因素吗?听起来非常适合在个人设备上长达 24 小时“记住我”。 [与 Q 不同,我会将其与存储在服务器上的令牌进行比较。]
  • 如果您乐于记住我,那么您已经对某些事情感到满意。您可能会告诉用户不要在公共或共享机器上执行此操作,但会发生错误。所以记住我不适合需要最低安全性的网站。今天在您不需要安全性时添加它,然后在明天添加更多需要更好安全性的功能并且忘记禁用记住我或重新验证用户以执行风险操作(例如更改该电子邮件)是未来可能遇到的问题。实施自己的安全功能是出了名的危险。更明智地使用图书馆或免费的 teir auth0
  • @simbo1905 - 谢谢。我不想重新发明轮子——我认为我需要对这个主题做更多的背景研究。您能否推荐指向已实施解决方案的讨论/评论/比较的链接?我正在为接待员电脑上的基于浏览器的应用程序寻找一种在会话之外持续存在的解决方案,最长可达 24 小时。 [理想情况下,当前会话 cookie 使应用程序在这种情况下保持足够长的时间;但我还想提供一种替代方法,这种方法将在更广泛的情况下持续存在。]
  • 上次我仔细查看是 2014 年,所以我建议您尝试找到一个流行且积极使用的库,用于对您使用的语言/框架进行身份验证。
【解决方案2】:

我知道这个问题现在已经很老了,但我认为用更新的答案更新答案可能是个好主意。对于像我这样可能偶然发现它的人。

为了提高性能,我正在考虑尝试 消除一个普通的“会话cookie”,但加密所有信息 cookie 本身。

现在有个大问题:这是个坏主意吗?

简短的回答是:不,这不是一个坏主意,事实上这是一个非常好的主意,并且已成为行业标准。

长答案是:这取决于您的实施。会话很棒,速度很快,很简单,而且很容易保护。然而,作为无状态系统运行良好的地方,部署起来有点复杂,可能超出了较小项目的范围。

实现基于令牌(cookies)的身份验证系统现在非常普遍,并且非常适用于无状态系统/api。这使得使用单个帐户对许多不同的应用程序进行身份验证成为可能。 IE。使用 Facebook / Google 登录 {unaffiliated site}。

实施这样的 oAuth 系统本身就是一个大课题。所以我会给你一些文档oAuth2 Docs。我还建议您查看Json Web Tokens (JWT)

额外的

最后一点:我正在尝试提出减少数据库的解决方案 加载。这只是我正在研究的解决方案之一

Redis 可以很好地卸载数据库查询。 Redis 是一个内存中的简单存储系统。非常快的~临时存储,有助于减少数据库命中。

【讨论】:

    【解决方案3】:

    更新:此答案与实际提出的问题有关,而不是与这个问题真正与 JWT 有关的想象历史有关。

    与今天的签名令牌最重要的偏差是:

    1. 最初提出的问题并未表明对令牌生成中需要秘密的任何理解。密钥管理对 JWT 至关重要。
    2. 提问者表示他们无法使用HTTPS,因此他们缺乏对令牌的保密性以及令牌与请求之间的绑定。同样,即使是成熟的 JWT 也无法保护普通的 HTTP 请求。
    3. 当修改问题以解释如何合并秘密时,选择的秘密需要服务器端状态,因此不符合 JWT 等提供的无状态性。

    即使在今天,这种自制方法也是一个坏主意。遵循 JWT 之类的标准,其中的方案及其实施都经过了仔细审查和完善。


    是的,这是个坏主意。

    对于初学者来说,它并不安全。使用此方案,攻击者可以生成自己的 cookie 并冒充任何用户。

    会话标识符应由加密随机数生成器从较大的(128 位)空间中选择。

    它们应该保密,这样攻击者就无法窃取它们并冒充经过身份验证的用户。任何执行需要授权的操作的请求都应该是防篡改的。也就是说,整个请求必须具有某种完整性保护,例如 HMAC,以便其内容不能被更改。对于 Web 应用程序,这些要求不可避免地导致 HTTPS。

    您有哪些性能问题?我从未见过有适当的安全性创建任何类型的热点的 Web 应用程序。


    如果频道不具备隐私性和完整性,您就会面临中间人攻击。例如,在没有隐私的情况下,Alice 将她的密码发送给 Bob。 Eve 窥探到它,稍后可以以 Alice 的身份登录。或者,在部分完整性的情况下,Alice 将她签名的 cookie 附加到购买请求中并将它们发送给 Bob。 Eve 拦截了请求并修改了送货地址。 Bob 验证了 cookie 上的 MAC,但无法检测到地址已被更改。

    我没有任何数字,但在我看来,中间人攻击的机会在不断增加。我注意到餐厅使用他们为客户提供的用于信用卡处理的 Wi-Fi 网络。如果他们的流量不通过 HTTPS,图书馆和工作场所的人通常很容易被嗅探。

    【讨论】:

    • 嗨 Erickson,没有 hmac 随机数/秘密,黑客如何生成 cookie?
    • @Evert 我回答了这个问题。
    • @Evert - 抱歉,您似乎在我发帖时编辑了您的帖子以添加秘密。使用强密钥,攻击者将无法伪造这些令牌,并且它们在某些情况下很有用。但是,尚不清楚您打算如何使用它们。您是否要继续使用 HTTPS,但只是摆脱存储经过身份验证的用户身份的内存会话?
    • 对此感到抱歉.. 我忘了添加它,后来才添加它。不幸的是,HTTPS 对我们来说是遥不可及的。我一直在推动它用于实际登录阶段,但使用我们系统的人设置自己的域名,SSL 可能有点复杂和昂贵。我们使用 PHP,会话数据存储在 MySQL 数据库中。我们一直在经历一些成长的痛苦,我试图找出是否可以将会话完全转移给客户。更“无国籍”的感觉更好。解决它的另一种方法是大量使用 memcache 之类的东西,我也在研究一下 =)
    【解决方案4】:

    您不应该重新发明轮子。开发平台附带的会话处理程序更安全,当然也更容易实现。 Cookie 应始终是链接到服务器端数据的非常大的随机数。包含用户 ID 和时间戳的 cookie 无助于加强会话免受攻击。

    这个提议的会话处理程序比为每个会话使用加密随机数更容易受到攻击。攻击场景如下。

    您可能在所有会话的 HMAC 计算中使用相同的密钥。因此,攻击者使用自己的帐户登录可能会暴力破解此秘密。通过查看他的会话 ID,他可以获得除秘密之外的所有内容。然后攻击者可以暴力破解秘密,直到可以复制 hmac 值。使用这个秘密,他可以重建一个管理cookie并更改他的user_id=1,这可能会授予他管理访问权限。

    【讨论】:

    • 代码只是伪代码,我想添加一个秘密,所以我现在做了。我很清楚我平台的会话系统是如何工作的,只是我正在处理数百万个会话,我需要跳出框框思考。我很欣赏这个答案,但我是一个坐着的程序员。为什么你认为人们重新计算秘密是微不足道的。 Amazon AWS 和 OAuth 大量使用它。
    • @Evert 没有秘密是微不足道的,有秘密然后你需要攻击者暴力破解这个值。加密随机数更安全
    • 我不想表现出防御性,我只是想澄清一下我的情况。如果秘密将基于用户的 id 和/或密码以及随机字符串,这不会使其变得更加困难吗?你是说这不可能正确完成吗?
    • 顺便说一句,暴力破解是个好点,不想破坏它,它确实让我意识到它需要一个非常强大的键。
    • 可以说,当 SQL 注入成为可能时,会话劫持不再是一个问题。在数据库中散列密码的主要原因是恶意用户无法将密码用于最终用户可能订阅的其他服务。所以是的,一旦可以直接访问数据库,用户的会话就会受到损害。我相信任何将会话存储在数据库中的人也是如此(并不罕见)。
    【解决方案5】:

    是什么让您认为与安全会话 ID 相比,这将提高性能并从会话的服务器端组件检索用户 ID 和时间信息?

    如果某些东西必须是防篡改的,请不要将它放在幼儿手中。例如,即使有防篡改锁定,也不要将其提供给客户端。

    忽略意识形态问题,这看起来相当不错。你没有随机数。你应该添加那个。只是一些随机垃圾随用户 ID 和时间一起存储,以防止重播或预测。

    【讨论】:

    • 目前我们的会话存储在一个主-主数据库中,由一组网络服务器使用。即使它是一个简单的 BTREE,我们也希望减少占用空间。修剪会话使 io 飞速发展。
    • @Evert 这些表的索引是否正确?你不应该从那里看到“屋顶”I/O。
    • @DougGale:你在回答很多很多年前的问题。
    猜你喜欢
    • 1970-01-01
    • 2018-06-10
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 2015-05-02
    • 1970-01-01
    • 1970-01-01
    • 2011-04-18
    相关资源
    最近更新 更多