ChatGPT解决这个技术问题 Extra ChatGPT

REST 身份验证方案的安全性

背景:

我正在为 REST Web 服务设计身份验证方案。这并不“真的”需要安全(它更像是一个个人项目),但我想让它尽可能安全,就像锻炼/学习体验一样。我不想使用 SSL,因为我不想要麻烦,而且主要是设置它的费用。

这些 SO 问题对我开始特别有用:

RESTful 身份验证

保护 REST API/Web 服务的最佳实践

最佳 SOAP/REST/RPC Web API 的示例?你为什么喜欢他们?他们有什么问题?

我正在考虑使用 Amazon S3's authentication 的简化版本(我喜欢 OAuth,但它似乎对我的需要来说太复杂了)。我将服务器提供的随机生成的 nonce 添加到请求中,以防止重放攻击。

要解决这个问题:

S3 和 OAuth 都依赖于对请求 URL 以及一些选定的标头进行签名。他们都没有为 POST 或 PUT 请求签署请求正文。这是否容易受到中间人攻击,它保留 url 和 headers 并用攻击者想要的任何数据替换请求正文?

似乎我可以通过在签名的字符串中包含请求正文的哈希来防止这种情况。这安全吗?

Amazon S3 可以包含 Content-MD5 作为标头字符串的一部分,以防止您描述的 MITM 攻击。
MD5 是一个非常弱的散列函数,多年来一直不鼓励使用它:en.wikipedia.org/wiki/MD5。现在使用 SHA2。 MD5 是身份危机猪的口红。
Startcom 提供免费的 SSL 证书,不会在主流浏览器中引发证书警告
@SeanKAnderson(咆哮:当互联网受到间谍机构的围攻时,我发现人们谈论 99.99999%s 是荒谬的,这些机构在 2008 年已经自动化了很多攻击——这是一种处理实际问题的奇怪方式—— “Naaah,不会有问题的;我的祖母将无法破解它”
@Plato 这些天我推荐 LetsEncrypt 以获得免费的 SSL 证书

C
Community

先前的答案仅在数据传输的上下文中提到 SSL,实际上并未涵盖身份验证。

您确实在询问安全地验证 REST API 客户端。除非您使用 TLS 客户端身份验证,否则单独的 SSL 不是 REST API 的可行身份验证机制。没有客户端身份验证的 SSL 仅对服务器进行身份验证,这与大多数 REST API 无关,因为您确实想要对客户端进行身份验证。

如果您不使用 TLS 客户端身份验证,则需要使用基于摘要的身份验证方案(如 Amazon Web Service 的自定义方案)或 OAuth 1.0a 甚至 HTTP 基本身份验证(但仅通过 SSL)。

这些方案验证请求是由预期的人发送的。 TLS (SSL)(无客户端身份验证)确保通过网络发送的数据不会被篡改。它们是独立但互补的关注点。

对于那些感兴趣的人,我已经扩展了关于 HTTP Authentication Schemes and how they work 的 SO 问题。


确切地。就您的 API 而言,SSL 唯一验证的是它正在处理的调用在途中没有被弄乱。 API 仍然不知道谁在与它交谈,也不知道他们是否应该拥有访问权限。
好答案。我还建议您查看这些出色的资源 .. owasp.org/index.php/Web_Service_Security_Cheat_Sheetowasp.org/index.php/REST_Security_Cheat_Sheet(草案)
只是一个小问题,但使用 SSL 还具有防止窃听和中间人攻击的额外好处。
@Les Hazlewood 您能否解释一下基于 Https 的 HTTP Basic 身份验证如何帮助确定服务器知道与谁交谈?
@Les Hazlewood 在这里我问了一个问题; tnx stackoverflow.com/questions/14043397/…
m
mahemoff

REST 意味着使用网络标准,而网络上“安全”传输的标准是 SSL。其他任何东西都会有点时髦,需要为客户端进行额外的部署工作,这些客户端必须有可用的加密库。

一旦您承诺使用 SSL,原则上就不需要任何花哨的身份验证。您可以再次使用 Web 标准并使用 HTTP 基本身份验证(与每个请求一起发送的用户名和秘密令牌),因为它比复杂的签名协议简单得多,并且在安全连接的上下文中仍然有效。您只需要确保密码永远不会超过纯文本;因此,如果曾经通过纯文本连接接收到密码,您甚至可以禁用密码并邮寄给开发人员。您还应该确保凭据在收到时不会记录在任何地方,就像您不会记录常规密码一样。

HTTP Digest 是一种更安全的方法,因为它可以防止传递秘密令牌;相反,它是服务器可以在另一端验证的哈希值。尽管如果您采取了上述预防措施,对于不太敏感的应用程序可能会有点过分。毕竟,用户登录时的密码已经以纯文本形式传输(除非您在浏览器中进行了一些花哨的 JavaScript 加密),同样,他们在每个请求上的 cookie 也是如此。

请注意,对于 API,客户端最好传递令牌(随机生成的字符串)而不是开发人员登录网站时使用的密码。因此,开发人员应该能够登录您的站点并生成可用于 API 验证的新令牌。

使用令牌的主要原因是如果它被泄露,它可以被替换,而如果密码被泄露,所有者可以登录开发者的帐户并使用它做任何他们想做的事情。代币的另一个优势是您可以向同一个开发人员发行多个代币。也许是因为他们有多个应用程序,或者因为他们想要具有不同访问级别的令牌。

(已更新以涵盖仅建立 SSL 连接的含义。)


我认为您可以以每年 30 美元的价格获得 GoDaddy ssl 证书。我很震惊地看到 Verisign SSL 证书的价格是多少(如果我没记错的话,每年 600 美元还是什么?)但是 GoDaddy 选项是完全可行的。
除非您使用 SSL/TLS 相互身份验证,并且用户/客户端使用的证书受服务器信任,否则您还没有将用户身份验证到服务器/应用程序。您需要做更多的事情来验证用户对服务器/应用程序的身份。
Ryan:与您使用 Django 或 Rails 等 Web 应用程序框架生成响应所使用的相比,如今的 SSL 加密只需要非常少量的处理能力。
startcom 的证书是免费的并且得到广泛认可。 cacert.org 是一个开放的替代方案,但认可度较低
这并没有解决关于身份验证的问题。
w
wowest

或者您可以使用已知的解决方案来解决这个问题并使用 SSL。自签名证书是免费的,它是个人项目吗?


自签名证书是免费的,但 AFAIK 你仍然需要一个静态 IP。
@dF 除了商业付费证书的某些许可要求外,不需要拥有静态 IP。
如果您可以控制两端(客户端和服务器)的证书存储,这可能是一个可行的选择,但是......证书管理和分发在生产环境中可能比在开发环境中复杂得多。在做出承诺之前,请务必了解此替代方案的复杂性。
Z
ZaDDaZ

如果您需要将正文的哈希作为 URL 中的参数之一,并且该 URL 是通过私钥签名的,那么中间人攻击只能将正文替换为会生成相同的哈希。至少现在很容易使用 MD5 哈希值,当 SHA-1 被破坏时,你就明白了。

为了保护正文不被篡改,您需要对正文进行签名,中间人攻击不太可能破坏该签名,因为他们不知道生成签名的私钥.


想出一个将生成与有效内容相同的 md5 哈希的字符串可能比它应该的要容易得多,但是想出一个哈希到相同值的有效内容的邪恶版本仍然非常困难。这就是为什么 md5 不再用于密码哈希,但仍用于验证下载的原因。
d
djsadinoff

事实上,原始的 S3 身份验证确实允许对内容进行签名,尽管 MD5 签名较弱。您可以简单地强制他们在 HMAC(要签名的字符串)中包含 Content-MD5 标头的可选做法。

http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html

他们新的 v4 身份验证方案更加安全。

http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html


L
LiorH

请记住,您的建议会使客户端难以与服务器通信。他们需要了解您的创新解决方案并相应地加密数据,这种模型对于公共 API 来说并不是那么好(除非您是 amazon\yahoo\google..)。

无论如何,如果您必须加密正文内容,我建议您查看现有的标准和解决方案,例如:

XML 加密(W3C 标准)

XML Security