数据库级别的 UUID 用作安全措施,而不是真正的权限控制



数据库级别的UUID是否可以用作安全措施而不是真正的权限控制?

考虑一个 Web 应用程序,其中所有 servlet 都通过将会话 ID 连接到调用它的用户(通过 Web 客户端)来实现"正常"访问控制。因此,所有用户都经过身份验证。

所需的下一个安全级别是经过身份验证的用户是否实际"拥有"正在更改的数据。例如,在 Web 应用程序中,这可能是编辑表单中的某些文本。客户端确保用户不会意外地做错事(JavaScript)。问题当然是,任何数量的网络工具都可以轻松重复浏览器的调用,并且只需更改 ID,即可编辑用户不"拥有"的 servlet 后面的数据库表中的不同行。

我的问题是,使用 UUID 作为数据库表中的键是否足够,从而使几乎不可能猜出有效的 ID (https://en.wikipedia.org/wiki/Universally_unique_identifier#Random_UUID_probability_of_duplicates)?据我所知,谷歌相册(http://www.theverge.com/2015/6/23/8830977/google-photos-security-public-url-privacy-protected)中使用了类似的方法,但我不确定它是否100%可比。

另一种选择是关闭,因为让每个 servlet 验证用户是否只对自己的数据执行操作,但在具有 200+ 个 servlet 和 50-100 个表的大型应用程序中,这可能是一项非常繁琐的任务,很容易发生错误。在我看来,这大大削弱了安全性,但我不确定这是否属实。

倾向于UUID解决方案,但我也很好奇是否有其他明显的方法来解决这个问题,我应该考虑。

更新:

我可能应该澄清一下,我的计划是使用应该是随机的UUIDv4。我知道熵在这里发挥了UUID的实际随机性,但据我所知,Java(这是选定的平台/语言)使用SecureRandom,它应该是"加密强"(链接)。

在这种情况下,维基状态(链接):换句话说,只有在未来 100 年每秒生成 10 亿个 UUID 之后,仅创建一个副本的概率才会约为 50%。

以这种方式使用 UUID 有两个主要问题:

  1. 如果没有其他身份验证方法,任何攻击者都可以简单地猜测 UUID,直到找到属于其他人的 UUID。谷歌相册不需要担心这一点,因为它们只使用 UUID 来混淆公开共享的照片视图;您仍然需要进行身份验证才能修改照片。这尤其危险,因为:
  2. UUID 旨在是唯一的,而不是随机的。您的 UUID 中可能存在可预测的模式,攻击者可以观察到并利用这些模式。此外,即使没有明确的模式,攻击者需要测试以找到有效 UUID 的数量也会随着用户群的增长而迅速减少。

我将始终建议使用安全、持续检查的身份验证。但是,如果您的用户群相当小,并且您仅使用它来混淆公共数据访问,那么以这种方式使用 UUID 可能没问题。即便如此,您也应该使用实际的随机字符串,而不是 UUID。

另一个选项是关闭,因为让每个 servlet 验证用户 仅对自己的数据执行操作,但在大型应用程序中 有 200+ 个 servlet 和 50-100 个表,这可能非常麻烦 容易发生错误的任务。在我看来,这削弱了 安全性要高得多,但我不确定这是否属实。

对于大型遗留应用程序,以后添加安全性始终是一项复杂的任务。你是对的 - 应用程序越复杂,验证安全性就越困难。复杂性是安全的主要敌人。

但是,这是最好的方法,而不是试图掩盖不安全的直接对象引用问题。

如果在查询字符串中使用这些 UUID,则 URL 中的此信息可能会记录在不同位置,包括用户的浏览器、Web 服务器以及两个终结点之间的任何正向或反向代理服务器。URL 也可能显示在屏幕上、添加书签或由用户通过电子邮件发送。当点击任何站外链接时,它们可能会通过 Referer 标头披露给第三方。将直接对象引用放入 URL 会增加攻击者捕获它们的风险。应用程序的现有用户随后撤销了对某些数据位的访问权限 - 他们仍然可以使用以前添加书签的 URL(或使用其浏览器历史记录)访问此数据。即使 ID 在 URL 机制之外传递,知道(或已经弄清楚)系统工作方式的本地攻击者也可能故意保存 ID 只是为了这个场合。

正如其他答案所说,GUID/UUID 并不意味着不可猜测,它们只是意味着唯一。当然,Java 实现确实会生成加密安全的随机数。但是,如果此实现在将来的版本中发生更改,或者如果您的系统移植到此功能不同的其他位置,该怎么办?如果要执行此操作,不妨使用自己的实现生成自己的加密安全随机数以用作标识符。如果你的标识符中有128位熵,那么任何人都完全不可能猜测它们(即使他们拥有世界上所有的计算能力)。

但是,由于上述原因,我建议您改为实施访问检查。

您试图通过希望密钥无法猜测来绕过授权控制。 这是一个安全禁忌。 根据您询问的对象,他们可能会将其称为不安全的直接对象引用或违反完整的中介原则。

正如 F. Stephen Q 所指出的,您假设 UUID 是唯一的并不意味着它们不可预测。 这里的威胁是,如果用户知道一些UUID,比如他自己的UUID,这是否允许他预测其他人的UUID? 这是一个非常真实的威胁,请参阅:警告:UUID 通常不符合安全要求。 特别要注意 UUID RFC 的内容:

不要假设 UUID 很难猜测;它们不应该用作 安全功能(仅拥有就授予的标识符 访问),例如。

您可以将 UUID 用于密钥,但仍需要进行授权检查。 当用户想要访问其数据时,数据库应标识数据的所有者,并且服务器逻辑需要强制当前用户与数据库声明所有者相同。

最新更新