适合 REST 的消息身份验证代码

信息安全 休息 http 验证
2021-08-13 00:25:38

我的 REST 服务目前使用 SCRAM 身份验证来为调用者和用户颁发令牌。

SCRAM 交易所发行的代币有一个到期时间,之后需要重复登录。我们还将发行没有过期的“无限”令牌,以简化个人(将我们的服务用于个人用途)的集成并为 JSONP 端点做准备。

我们有能力撤销调用者权限(令牌附加到的帐户)和禁止 IP,以及在任何时间段内对任何类型的请求施加配额。

然而,我还没有实现的一件事是请求的 MAC。正如我更多地考虑的那样,对于某些请求,我认为这是必要的,因为否则令牌可能会被盗,并且在我们识别它并停用相关的呼叫者帐户之前,可能会对我们的用户帐户造成一些损害。

在许多系统中,MAC 是从请求的正文或查询字符串生成的,但是这很难实现,因为我使用的是 ASP.Net Web API 并且不想读取正文两次。同样重要的是,我希望让呼叫者能够轻松访问服务,并且我需要能够同时支持桌面/移动应用程序以及 Web 浏览器。

所以我在想的是在注册时将MAC密钥发送给用户,并让他们计算请求MAC:

  • url,可能减去查询字符串
  • 动词
  • 请求 ip(虽然可能是某些移动设备上的障碍,但肯定是在 javascript 中)
  • UTC 客户端发出请求的日期和时间。

对于最后一个,我当然会让客户端在请求标头中发送该字符串 - 我可以使用它来确定请求是否足够“新鲜”。

我的想法是,虽然这并不能防止消息正文被篡改,但它确实可以防止恶意第三方使用模型请求作为模板来处理不同的请求。我相信只有在中间攻击中最具侵略性的人才能颠覆这一点,而且我认为我们的服务无法提供任何有价值的信息或能力来保证这一点。

这些服务也将使用 SSL 来处理敏感内容。如果我这样做,那么我将使用 HMAC-SHA-256 和使用 PRNG 生成的密钥。

这听起来够吗?我错过了什么吗?

在安全方面,我不认为我是初学者,但在处理它时,我总是如此。我被笼罩在疑问之中,所以我很高兴有这个社区可以呼吁!

2个回答

如果您使用 SSL 进行传输,并且正确执行,那么任何额外的 MAC 都是多余的;而且,当涉及到它时,SCRAM也是如此SCRAM 的一个卖点是它应该能够抵抗 SSL 使用不当的情况,即没有适当的服务器身份验证(不幸的是,它发生了)。但是在这种情况下,SCRAM 的安全论证相当薄弱,因为它无法防止中间人攻击; 而且,如果没有 MitM,SSL 中的基本纯密码已经很好了。SCRAM 与普通密码相比的唯一优势在于,在中间人攻击的情况下,攻击者不会立即获知密码。他仍然可以看到所有交换的数据,并且可以插入自己的命令,并且他获得了足够的数据来执行离线字典攻击,这是很少有密码能够毫发无损的。

在您添加 MAC 的建议中,您没有说明 MAC密钥的来源。这很关键。只要攻击者不知道密钥,MAC 就具有任何价值。但是如果客户端和服务器已经共享一个攻击者不知道的密钥,他们为什么还要为密码和 SCRAM 烦恼呢?让他们使用Pre-Shared Key TLS,即带有共享密钥的 SSL/TLS 作为相互认证和加密的基础:根本没有证书(所以没有证书验证会出错),操作流畅且快速。

更好的是,如果客户端和服务器共享一个密码,不想使用证书,害怕离线字典攻击,不想让服务器按原样存储密码,那么解决方案就是TLS-SRP客户端和服务器相对于一个共同的密码相互验证,服务器不存储密码,而只存储它的哈希等价物,并且密码对于离线字典攻击是安全的,即使在 MitM 尝试的情况下(不仅是尝试受阻,但攻击者甚至没有获得足够的数据来“在家尝试密码”)。


SCRAM 设计人员可能在某个时候被告知了 SRP,因为他们在规范的第 9 节中添加了以下段落:

可以使用防止这种攻击的身份验证机制(例如,EKE 类机制)。RFC 2945 [RFC2945] 就是这种技术的一个例子。WG 选择不使用类似 EKE 的机制作为 SCRAM 的基础。

他们没有给出拒绝PAKE协议的任何理由(他们不恰当地将其称为“EKE”,这只是第一个已知的 PAKE 协议的名称)。

对于大多数设置,我建议您只使用 HTTPS (SSL) 和 CSRF 令牌。这是用于保护 Web 应用程序/Web 服务的标准架构。如果您使用 HTTPS + CSRF 令牌,则不需要 MAC。

我会反对“仅将 SSL 用于敏感内容”的想法。这有一些问题。我建议在整个站点范围内使用 HTTPS。在此站点上搜索有关在站点范围内使用 SSL 的利弊以及如何实施它的信息。

我不知道您的界面是否仅用于编程用途,或者它是否也将被人类使用。如果是这样,HTTPS 也可能会为用户提供最佳可用性,前提是客户端有一个人坐在 Web 浏览器后面。