REST Web 服务的这个安全模型有什么缺陷吗?

信息安全 应用安全 验证 网络服务 休息
2021-09-07 09:26:04

我设计了一个需要身份验证的 REST Web 服务。它以类似于 Amazon Web Services 的方式处理身份验证,即:用户有一个ACCESS_KEY(比如,'abcd')和一个SECRET_KEY(比如,'aabbcc')。所述SECRET_KEY用于创建一个TOKEN:一个SHA-1使用的请求信息,例如:

GET path HTTP/1.1
Date: Mon, 23 May 2005 22:38:34 GMT
ACCESS_KEY: abcd
TOKEN: SHA1(SECRET_KEY + ACCESS_KEY + Date + path)

我可以检查TOKEN服务器并验证请求。到目前为止,我认为安全模型没有任何问题。

我唯一的问题是如何在SECRET_KEY从网页使用服务时提供。我想我可以将它作为 JavaScript 变量发送(连接是 HTTPS),然后简单地在 JavaScript 函数中使用该变量,将适当的标头添加到每个HTTPRequest. 初始身份验证可以使用标准的基于 cookie 的方法来完成(例如,依靠 Django 来处理会话)。

所以,架构看起来像:

  • 网站会话:由 Django 使用标准的基于会话的安全性处理 ( example.com)
  • 网站会话通过 HTTPS 接收SECRET_KEY作为 JavaScript 全局变量的 ,用于将适当的标头添加到每个HTTPRequest.
  • HTTPRequestsare made to ,api.example.com对 Django 会话是无视的:它只关心是否有适当的标头。

我相信这种方法是安全的,同时保持完全无状态的 REST API。我不使用标准 HTTP 身份验证(基本或摘要),因为我不想破解“您无法注销”问题,并且我想严格保持 API 为 REST。

您对这种方法有什么意见吗?如果它有缺陷,你将如何实现我的目标?

谢谢!

3个回答

我没有看到任何缺陷,但我确实认为你做得过火了。在我看来——我可能遗漏了一些东西——你使用令牌是因为你认为你应该这样做,而不是因为有正当的理由。

最好的方法是首先确定您的(安全)要求,然后寻找解决方案。

对于无状态 API,您应该考虑的一件事是重放攻击。你描述它的方式,你的协议听起来容易受到重放攻击。此外,由于每个请求都没有随机性,因此它可能会被 CSRF 滥用。我不确定这是否是 REST API 可以解决的问题,因为这是一个固有的 webapp 问题,但值得考虑。

最重要的是,如果您没有安全要求(和威胁环境),没有人可以评估您的安全是否正常。

我认为您应该坚持使用https。如果主要部分是在客户端 javascript 中生成的(例如,令牌的 sha1),那么 MITM 攻击的难度有多大,攻击者会将人们引导到您网站的伪造版本,其中 javascript 被更改以显示服务器的密钥?(例如,更改 DNS 并在公共 wifi 热点上欺骗站点。)

还有谁在生成日期(客户端或服务器)?令牌的有效期是多久?两分钟前生成/验证的令牌是否仍然有效?MITM 是否可以拦截有效令牌以执行特定请求并重放它(并通过重放来做一些恶意的事情)?

您能否确认您的 RESTful Web 服务有以下用例

  1. 其他服务/应用程序向您的服务发送请求。无需维护会话状态
  2. 来自浏览器的请求。

对于第一个用例,我认为您的方法很好。您可以考虑进行以下更改以使其变得更好 1. 使用 SHA256 而不是 SHA1(他们说现在 SHA1 并没有被认为太强大) 2. 确保发布的所有密钥都遵循适当的复杂性规则

我希望您在这里只谈论身份验证模型,而不是其他事情。如果您也在谈论其他事情,那么 SSL 应该在您的优先级列表中(出于多种原因)。

对于第二个用户案例,建议会有所不同,具体取决于您是要真正维护会话状态(不是真正的 REST ;))还是您可以接受来自浏览器的不相关的个​​人请求

我可以尝试根据用例(会话或无会话)给出一些建议