发送需要 SSL/TLS 的请求的正确 HTTP 响应是啥

Posted

技术标签:

【中文标题】发送需要 SSL/TLS 的请求的正确 HTTP 响应是啥【英文标题】:What is the proper HTTP response to send for requests that require SSL/TLS发送需要 SSL/TLS 的请求的正确 HTTP 响应是什么 【发布时间】:2011-02-03 00:42:56 【问题描述】:

我正在设计一个 RESTful API,其中一些调用是通过 HTTP 公开的,而一些调用需要 API 密钥并通过 HTTPS 进行加密。如果将 HTTP 请求发送到私有资源之一,我正在考虑应该发送什么响应代码。到目前为止,唯一让我跳出来的是 412 - Precondition Failed,但标准表明前提条件是由请求者而不是服务器施加的。

是否有适合这种情况的响应代码,还是我只需要让步并执行 400

【问题讨论】:

【参考方案1】:

我不能说这是否被 HTTP 客户端广泛接受,但严格来说 RFC,服务器应该响应:

HTTP/1.1 426 Upgrade Required
Upgrade: TLS/1.0, HTTP/1.1
Connection: Upgrade

来源:https://www.rfc-editor.org/rfc/rfc2817#section-4.2

【讨论】:

有趣。 RFC 和 OWASP 的建议不同。我更喜欢 OWASP 的版本——不响应请求而只丢弃数据包。使用 RFC 方法,中间人可以拦截响应(因为它还不是 https)并重定向到欺骗性网站。 是的,我同意 - 这绝对是一个漏洞。即使断开连接可能会令人困惑,但此处应优先考虑安全问题。另外,请注意,上述 RFC 现在已经有 10 年的历史了(在那个时候,安全性可能不像今天这样重要)。 https 众所周知,它是在 RFC 2818(HTTP over TLS)中指定的。 RFC 2817 几乎从未使用过。 @dasil003,请注意,IETF 规范将 TLS 称为“TLS”,因为它是 IETF 标准(SSL 不是):您可以轻松地阅读所有这些标准,同时牢记“SSL”(除了它确实会引用早期版本)。 RFC 2817 不是关于从 SSLv3 升级到 TLS (1.x),而是关于在同一连接上从纯 HTTP 升级到 SSL/TLS。 @SripathiKrishnan 即使您的服务器会丢弃 http 请求,中间人/拦截攻击仍然是可能的。实际上,除非客户端使用 https,否则无法保证他们得到的任何响应都不会被破坏。 肯定认为 MITM 的讨论想多了。 MITM 甚至可以在您丢弃数据包之前进行拦截。如果客户端尝试 http,则行为完成。 426 的目的是告诉客户的开发人员修复他们该死的代码。【参考方案2】:

强制 HTTP 客户端使用 HTTPS 的最安全方法是HTTP Strict Transport Security。

以前一个常见的建议是断开连接,但是这个practice has been removed in favor of HSTS(OWASP 网站)。

【讨论】:

1. HSTS 草案是moved to the IETF。 2.阅读它实际上并不能很好地回答OP的问题。 HSTS 在整个网站上强制使用 HTTPS。上面的海报希望某些资源可以通过 HTTP 获得,而其他资源只能通过 HTTPS 获得。所以不能使用 HSTS,因为它适用于所有资源。 这不能回答 OP 的问题。他问的是当客户端通过 http 连接时要做什么,而不是 HSTS 标头,后者仅在用户已经通过 https 连接时才有效。【参考方案3】:

要返回的相应错误代码类似于403.4 - SSL required。

虽然RFC for HTTP 1.1 中没有明确记录,但这种行为确实符合那里列出的要求:

服务器理解请求,但拒绝执行。授权将无济于事,并且不应重复请求。如果请求方法不是 HEAD 并且服务器希望公开请求未完成的原因,它应该在实体中描述拒绝的原因。如果服务器不希望向客户端提供此信息,则可以使用状态码 404(未找到)。

添加您自己的子代码(如 SSL 示例)在某些情况下可能会有所帮助,但由于此子代码对第三方没有意义,我建议不要这样做。

因此,您的最终错误消息将类似于“403 - 私有资源”。请注意,即使在缺少 API 密钥的情况下,也不应使用“401 - Unauthorized”,除非您的 API 密钥实际上可以在 WWW-Authenticate 标头字段中传输。

【讨论】:

请注意,IIS 状态代码是伪造的。 HTTP 状态代码仅由数字组成(正好 3 个)。请参阅w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1 另请注意,403 的原因短语是“禁止”,并且这不能修改。任何进一步的解释都应该在响应 body 中。 是的,尽管该子代码很吸引人,但我无法支持它的非标准化性质。 我同意其他评论者的观点,即不应使用子代码,但可以为普通的 403 设置一个案例。例如,这就是 Twitter 用于其 API 的内容。见dev.twitter.com/docs/security/using-ssl【参考方案4】:

返回带有原因短语“HTTPS 要求”的 403 似乎是一个实用的选择,也是我使用的。

见https://en.wikipedia.org/wiki/HTTP_403

重定向 REST Api 不是一个好主意,尤其是因为您可能不知道如何或什么正在使用您的服务。

【讨论】:

【参考方案5】:

只需发送一个重定向到相应的 https: URI。

更新

这是一个错误的答案 - 请参阅下面的 cmets

【讨论】:

存在安全风险。 “执行中间人攻击的攻击者可以拦截 HTTP 重定向响应并将用户发送到备用页面” - 来自 OWASP SSL 最佳实践 这并不能阻止用户仍然引用 http url,事实上,对于大多数 http 客户端,他们甚至不会看到发生了 http 重定向。隐藏问题可能不是您想要采取的方法。 是的,对不起。你们是对的。发送重定向是错误的做法。感谢您指出这一点。

以上是关于发送需要 SSL/TLS 的请求的正确 HTTP 响应是啥的主要内容,如果未能解决你的问题,请参考以下文章

System.Net.Http.HttpClient POST 未能创建 SSL/TLS 安全通道

SSL/TLS协议原理解读

SSLWebClient 请求 https 页面出错:未能创建 SSL/TLS 安全通道

C#动态调用webService出现 基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系。

SSL/TLS 握手过程详解***

Azure api 请求被中止:无法创建 SSL/TLS 安全通道。 http客户端在调用一些web api时