【问题标题】:Cookies signing with hash to validate integrity. Good idea?使用哈希签名的 Cookie 以验证完整性。好主意?
【发布时间】:2018-06-10 16:08:01
【问题描述】:

我想知道用哈希对 cookie 进行签名以检查其完整性是否是个好主意?首先,我确实意识到我不应该在 cookie 中存储任何敏感数据,而是使用会话。这正是我所做的。但我仍然对用户能够修改甚至不那么重要的数据感到不舒服。 (我有点安全偏执狂:))

我想出了以下解决方案。假设我们有 cookie:

  • PHPSESSID
  • site_lang
  • recently_viewed

现在,每当我更新 cookie 值时,我都会重新计算 cookie 的哈希值,其键为 cookie_hash,值为 md5(serialize($_COOKIE)+$secret) 唯一我没有使用 PHPSESSID 来计算和验证哈希,因为它不是由 CookieManager 类(我的自定义类)管理的,并且可能会使用新的会话 ID 和损坏的哈希进行刷新。 我担心的是,如果某些第三方包设置了它自己的 cookie,当然会绕过我的 CookieManager。它会崩溃哈希。那么这是个好主意吗?

【问题讨论】:

    标签: php validation security cookies hash


    【解决方案1】:

    MD5 在这方面很弱,而且你提出的方案 (hash(data||secret)) 无论如何都是有缺陷的。密码学很难,请不要尝试自己想出。 :)

    您可能正在寻找的东西已经被发明出来了,它被称为消息身份验证。看看HMAC 之类的东西,这是做非常相似的事情的一种正确方法。

    在大多数情况下,验证 cookie 值在 Web 应用程序中没有意义,也不会提供额外的安全性,但有 种情况,确实如此。您上面的示例似乎并非如此。 :) 例如,会话 id 已经是加密随机的,另外两个如果由用户更改通常不会造成伤害(但在非常特殊的情况下,它们可能会,尽管我无法提出合理的例子)。如果某些事情很重要并且不应由客户端(用户)更改,则可能应该将其存储在服务器端会话中。

    但是,您可以决定将应用程序状态存储在加密和/或经过身份验证的 cookie 中,其中一个原因可能是服务器上的应用程序无状态(例如,请参阅 Ruby on Rails 中的默认会话管理),以及在这种情况下,类似于您的想法(但做得正确)确实是解决方案,但它有其自身的一组风险(服务器端会话也是如此)。

    请注意,每当您在客户端上存储状态时,除了保密性和真实性之外,还会出现一种威胁是重放。这也会影响你的想法。如果用户可以更改 last_viewed cookie,则表示您的应用程序存在问题,但您仍然不想将其放入会话中。您正确地验证了 cookie,甚至可能对其进行了加密,客户端无权访问。但是,如果在某个时候,用户保存了 cookie,并在不同的会话中重放它呢? (好的,您的示例尝试同时保护所有 cookie,这可能会使这有点困难,但您明白了,重放仍然是一个潜在问题。)

    简而言之,您很可能不需要此功能,但如果您需要,请使用适当的消息身份验证(例如 authenticated encryption 或适当的 MAC,例如 HMAC)。

    【讨论】:

    • 感谢您提供详细的解答。我的应用程序实际上并不需要这种级别的安全性,所以我正在考虑一些快速的解决方案,而不是使用一些经过时间验证的解决方案。 (但当然,如果它对我的应用程序至关重要,我会调查它)。我想知道这个确切的“肮脏”技巧是否可以用这个解决方案来解决问题和可能的陷阱。我也意识到 md5 很弱,但我认为对于这个微不足道的任务来说已经足够了......你能告诉我更多关于基本安全的简单哈希值 + 秘密有什么问题吗?
    • 是的,重放是一个潜在的问题。谢谢你指出。 (完全忘记了)也许一些基于 ip 的指纹可以解决问题?
    • 但是,如果它对我的应用程序至关重要的话,我肯定会对这个主题进行完整的研究......但对于这个项目来说,它并不重要。所以我的问题更多的是'如果实现起来相当简单,或者如果它有太多的陷阱不能做到这一切,为什么不这样做呢?谢谢:)
    【解决方案2】:

    我不知道你对PHP和Web开发有多深,如果我的回答水平低,请见谅。

    如果您偏执,您应该阅读更多关于 PHP、会话、cookie、哈希算法等的信息。

    例如:

    PHP session handling

    PHP session configuration

    PHP session security

    有了这个,你可以稍微修改你的会话和处理来满足你的偏执。

    顺便说一句,您不应该使用 md5 之类的东西来使您的 Web 应用程序更安全。


    如果我了解您想要做什么,您希望将序列化会话数组的哈希值和秘密/盐 写入会话,以验证会话及其数据的完整性。

    如果这是你的动机,你真的应该重新考虑,至少在我看来。

    会话只是您服务器上的一个文件(在用户系统上,它是 firefox 或其他东西的 sqlite 数据库中的数据库条目,但没有您写入 cookie 数组的数据,该数据只是写入服务器) 并且会话 ID 是服务器上此数据的文件名/路径,除非您的会话保存在数据库中。

    因此,使用您的方法,您只需保存值以验证要验证的相同数据(在服务器上)中数据的完整性。

    你想把秘密保存在哪里?

    我觉得有点没用。

    根据您的需要和应用程序的需要,您可以搜索关键字会话 TAN,您可以设置一个额外的 cookie,其中包含您保存在会话中的随机值以相互验证,您可以保存并检查 IP (取决于您所在国家/地区的法律和您的用户连接方式)、缩短会话生命周期等等。

    您还可以设置诸如 session.cookie_httponly 之类的 ini 指令(如果您不想通过 JavaScript 之类的脚本语言访问会话 cookie,我建议您这样做),您可以在上面的链接中找到更多信息。

    有些事情是信仰的问题,有些事情是显而易见的。

    深入挖掘并了解技术在幕后的工作原理,您可以自己更轻松地做出决定。

    【讨论】:

    • 对不起,我这里根本不是在谈论会话。仅 cookie 值。
    • 不,对不起。我错过了重点。可能有点晚了。
    • 但是要向我澄清您的问题:当您说“使用哈希签名 cookie”时,您到底想做什么?你到底想对md5(serialize($_COOKIE)+$secret)的结果做什么,你把它保存在哪里;关于会话、数据库、文本文件、POST 数组(这更像是一个笑话,但有些人在做疯狂的事情)?但总的来说,我认为验证用户可以操纵的数据的完整性并不是一个坏主意。如果您尽一切可能将风险降至最低(除此之外,您还可以关闭风险),至少对我而言,这不是一种默默无闻的安全措施。
    • md5(serialize($_COOKIE)+$secret) 存储为带有密钥 cookie_hash 的 cookie。然后我检查这个值对于当前的 cookie 值是否正确(除了键 PHPSESSID 和 cookie_hash 本身)
    • @Marc 但是用户没有秘密,他无法制作有效的cookie哈希,所以这个想法是有效的,只有问题中的实现有缺陷(我同意整个对于大多数用例来说,这毫无意义),请参阅我的答案。
    猜你喜欢
    • 1970-01-01
    • 2014-12-10
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 2011-03-15
    • 2013-04-19
    • 2021-01-22
    • 2014-02-06
    相关资源
    最近更新 更多