以明文(在数据库中)存储 API 密钥如何安全?

信息安全 bcrypt
2021-08-25 16:45:43

这个问题的答案API 机密可以以纯文本形式存储还是可以解密?让我有些不安。我正在努力思考如何以明文形式存储密钥是安全的。

这就是我想象的基于 API 访问密钥/密钥的系统的工作方式:

  1. 客户端获取请求文本并应用 HMAC 函数secretKey,导致signature
  2. 客户端添加signatureaccessKey请求(有效地作为身份验证标头)并发送到服务器
  3. 服务器accessKey从请求中提取并查找对应的serverSecretKey
  4. 服务器获取请求文本并应用服务器版本的 HMAC 函数serverSecretKey,导致serverSignature
  5. 服务器signature比较serverSignature如果它们匹配,很好,我们很好 - 我们知道客户端同时拥有有效的访问密钥和有效的密钥

所以在我继续之前,如果上述内容不正确,那么这个问题的其余部分或多或少将毫无意义 - 所以请让我知道上述对 API 访问/密钥的理解是否有效:-)

假设我的理解是有效的——我的问题又回到了密钥是如何存储的——它必须以明文形式存储才能使上述系统正常工作。

那么,如果攻击者获得了对我的数据库的访问权限,该数据库拥有我所有客户的 API 访问密钥和密钥,会发生什么?难道他们不能轻松地使用他们喜欢的任何访问/密钥组合,并愉快地冒充任何客户吗?

我从bcrypt-ed 密码的角度来看这个。如果攻击者使用大量bcrypt-ed 密码访问数据库,他们需要做大量工作才能使该数据库对他们有价值,因为暴力破解一组bcrypt-ed 密码的计算成本很高。这感觉比将秘密 API 密钥以明文形式存储在某个数据库中要安全得多。

看起来 API 访问密钥/密钥组合实际上只提供了防止篡改消息的保护(因为在上面的步骤 #1 和 #2 中计算的数字签名与密钥相关联)并且并没有真正提供任何保证客户就是他们所说的那个人。我看不出它如何提供与bcrypt-ed 密码相当的安全级别

我在这里想念什么?

3个回答

你对此的想法太非黑即白:安全或不安全。这里没有安全,只有一系列风险。

提供这些 API 的公司正在做出判断,并试图平衡风险与绩效。并非所有这些 API 调用都需要通过 SSL 进行。想想上传一张图片到S3,需要加密吗?可能不是。关键要求是调用经过身份验证授权想想对 SDB 或 SQS 的一百万个不同的调用,SSL 会在客户端和服务器端产生多少开销?基本上 SHA2 速度快,SSL 成本高,现在乘以 1,000,000。

将 API 密钥以明文形式保存在服务器端是否存在风险?当然,但这些公司正在打赌,他们可以在关键商店周围采取其他缓解措施,将风险降低到可接受的水平。(最终,如果我可以访问您的密钥存储,无论是散列还是明文,我都可以做一些恶意的事情,比如用我的密钥交换你的密钥。)

关于您的陈述:“并不能真正保证客户就是他们所说的人”

几乎所有的身份验证方案都是如此。如果有人使用我的用户名和密码登录此站点,则不能证明他们是我,而只是证明他们拥有我的凭据。如果有人使用我的指纹解锁生物识别锁,则表明他们有某种方式提供我的指纹以使锁接受它。这里的变化是多么困难。窃取凭据可能并不难,冒充指纹可能更难但并非不可能。

我最近添加了另一个我认为在这里也相关的问题的答案。我已经稍微编辑了我的答案,以更直接地解决您的问题:

API 密钥和密码之间还有一个更重要的区别。API 密钥对您的站点是唯一的。使密码安全性如此重要的部分是密码共享。如果有人掌握了用户保存在您网站上的密码,那么受到威胁的不仅仅是您的网站:用户使用该密码(和电子邮件/用户名)的所有其他网站。

API 密钥是一个完全不同的场景,因为它对您的站点是唯一的。结果,如果它被盗,攻击者可以访问您的网站,但没有任何东西可以用来攻击该人的银行/电子邮件/等。这意味着 API 密钥更类似于会话标识符而不是密码。

从安全的角度来看,如果您将 API 密钥视为会话 ID 而不是密码,您会更清楚地看到问题,尤其是在 API 密钥可以自动分配的情况下(OAuth 等)。是的,API 密钥可能会被盗,这会导致您的帐户被盗,但密钥容易被盗的方式与密码被盗的方式大不相同。特别是,密码(理论上)只存储在两个地方:用户的头部和您的数据库。因此,您的数据库是密码安全性的最大威胁(如果我们忽略网络钓鱼攻击),并且在您的数据库被盗用纯文本密码的情况下,密码重用对最终用户的实际危险非常高。

但是,在会话标识符或 API 密钥的情况下,这些分析都不是真的。API 密钥存储在您的数据库中,但它们也存储在使用密码的任何客户端中。这可能存在于前端 javascript 应用程序(易受 XSS 攻击)、与 API 集成的服务器上的配置文件(易受完全不同的攻击集)的内存中,或者谁知道还有哪里。因此,数据库不再是获取 API 密钥访问权限的主要攻击媒介。这肯定会改变安全优先级。

再强调一点,会话标识符是查看 API 密钥的正确视角。任何依赖会话来存储用户数据的网站通常都有一个会话 ID,该 ID 也存储在数据库中,并与用户浏览器一起存储在 cookie 中。因此,如果您的数据库被黑客入侵并下载,您的用户会话将完全受到威胁。恶意用户可以获取会话 ID,为您的网站编辑他们的 cookie,然后几乎不费吹灰之力地以任何用户身份登录。在将会话 ID 存储到数据库之前对其进行哈希处理可以阻止这种特定的攻击,但对于阻止更常用于窃取会话的 XSS 攻击却无济于事。

简而言之,它不是,但是密钥不一定需要以明文形式存储在服务器上。它本身可以使用作为客户端请求的一部分的信息进行加密(但不像其他人解释的那样进行散列)。

同样,如果您登录到显示您的密钥的服务,则无需以明文形式存储密钥,因为它们可以使用用于登录的密码的单向派生进行加密,并且与会话保持关联. 虽然可以在访问会话数据的情况下发现密钥,但任何时候只有一部分客户端密钥处于危险之中。