3. 通用建议 (General Recommendations)
本节给出安全使用 TLS 的通用建议.与密码套件相关的建议在下一节讨论.
3.1. 协议版本 (Protocol Versions)
3.1.1. SSL/TLS 协议版本 (SSL/TLS Protocol Versions)
停止使用较旧且安全性较低的 SSL/TLS 版本, 并开始使用较新的安全版本, 这两点同样重要.因此, 关于 TLS/SSL 协议版本的建议如下:
-
实现禁止协商 SSL version 2.
理由: 当前 SSLv2 被认为是不安全的 [RFC6176].
-
实现禁止协商 SSL version 3.
理由: SSLv3 [RFC6101] 相比 SSLv2 有所改进并修补了一些重要安全漏洞, 但不支持强密码套件.SSLv3 不支持 TLS 扩展, 而其中一些扩展, 例如 renegotiation_info [RFC5746], 对安全至关重要.此外, 随着 Padding Oracle On Downgraded Legacy Encryption (POODLE) 攻击 [POODLE] 出现, SSLv3 已被广泛认为从根本上不安全.更多细节见 [RFC7568].
-
实现禁止协商 TLS version 1.0 [RFC2246].
理由: TLS 1.0 发布于 1999 年, 不支持许多现代强密码套件.此外, TLS 1.0 对基于密码块链接 (CBC) 的密码套件缺少逐记录初始化向量 (IV), 也未警告常见填充错误.本节中这些建议与 [RFC8996] 保持一致.
-
实现禁止协商 TLS version 1.1 [RFC4346].
理由: TLS 1.1 发布于 2006 年, 相比 TLS 1.0 是安全性改进, 但仍不支持某些更强密码套件, 这些套件在 2008 年 TLS 1.2 标准化时引入, 包括本文为 TLS 1.2 推荐的密码套件, 见第 4.2 节.
-
实现必须支持 TLS 1.2 [RFC5246].
理由: 当前 TLS 1.2 的实现和部署比 TLS 1.3 更广泛.只要遵循本文建议来缓解已知攻击, 使用 TLS 1.2 与使用 TLS 1.3 一样安全.对于大多数复用 TLS 和 DTLS 的应用协议, 没有立即只迁移到 TLS 1.3 的必要.事实上, 许多应用客户端依赖尚不支持 TLS 1.3 的 TLS 库或操作系统, 主动弃用 TLS 1.2 会造成严重互操作问题, 反而损害安全.不过, 未来版本的本 BCP 预计会在适当时弃用 TLS 1.2.
-
实现应支持 TLS 1.3 [RFC8446], 且如果已实现, 必须优先协商 TLS 1.3 而不是更早 TLS 版本.
理由: TLS 1.3 对协议进行了重大重构, 解决了 TLS 1.2 的许多安全问题.只要实现支持 TLS 1.2, 即便默认使用 TLS 1.3, 也必须遵循本文关于 TLS 1.2 的建议.
-
集成 TLS/DTLS 握手协议和/或记录层的新传输协议必须只使用 TLS/DTLS 1.3, 例如 QUIC [RFC9001] 采用了这种方式.采用 TLS/DTLS 进行信道或会话加密的新应用协议必须同时集成 TLS/DTLS 1.2 和 1.3.不过, 在少数不关心广泛互操作的情况下, 应用协议设计者可以选择放弃 TLS 1.2.
理由: 安全部署 TLS 1.3 明显比安全部署 TLS 1.2 更容易且更不易出错.设计 QUIC 这类新的安全传输协议时, 没有理由支持 TLS 1.2.相反, 复用 TLS 的新应用协议需要同时支持 TLS 1.3 和 TLS 1.2, 以利用底层库或操作系统对两个版本的支持.
本 BCP 适用于 TLS 1.3、TLS 1.2 和更早版本.读者不应假定本文建议会适用于未来任何 TLS 版本.
3.1.2. DTLS 协议版本 (DTLS Protocol Versions)
DTLS 是 TLS 面向 UDP 数据报的改编, 在 TLS 1.1 发布时引入.关于 DTLS 的建议如下:
-
实现禁止协商 DTLS version 1.0 [RFC4347].
DTLS 1.0 对应 TLS 1.1.
-
实现必须支持 DTLS 1.2 [RFC6347].
DTLS 1.2 对应 TLS 1.2.不存在 DTLS 1.1.
-
实现应支持 DTLS 1.3 [RFC9147], 且如果已实现, 必须优先协商 DTLS 1.3 而不是更早 DTLS 版本.
DTLS 1.3 对应 TLS 1.3.
3.1.3. 回退到较低版本 (Fallback to Lower Versions)
TLS/DTLS 1.2 客户端禁止回退到更早 TLS 版本, 因为这些版本已经被弃用 [RFC8996].因此, 客户端不再需要降级保护 Signaling Cipher Suite Value (SCSV) 机制 [RFC7507].此外, TLS 1.3 实现了新的版本协商机制.
3.2. 严格 TLS (Strict TLS)
以下建议用于帮助防止 "SSL Stripping" 和 STARTTLS 命令注入, 这些攻击在 [RFC7457] 中有总结:
-
许多现有应用协议设计于 TLS 普及之前.这些协议通常以两种方式之一支持 TLS: 使用单独端口进行仅 TLS 通信, 例如 HTTPS 的 443 端口; 或使用动态升级方式把未加密信道升级为受 TLS 保护的信道, 例如 IMAP 和 XMPP 等协议中的 STARTTLS.不论保护通信信道的机制是仅 TLS 端口还是动态升级, 重要的是信道的最终状态.当协议同时定义动态升级方法和独立的仅 TLS 方法时, 实现必须支持独立的仅 TLS 方法, 管理员也必须配置为优先使用该方法而不是动态升级方法.当协议只支持动态升级方法时, 实现必须为管理员提供一种严格本地策略, 用于禁止在未协商 TLS 信道时使用明文, 且管理员必须使用该策略.
-
面向万维网使用的 HTTP 客户端和服务器实现, 见第 5 节, 必须支持 HTTP Strict Transport Security (HSTS) 头字段 [RFC6797], 以便 Web 服务器声明自己愿意只接受 TLS 客户端.除非部署方式会使 HSTS 实际削弱整体安全, 例如第 11.3 节 [RFC6797] 所述自签名证书场景, Web 服务器应使用 HSTS 表示愿意只接受 TLS 客户端.非 HTTP 应用协议也存在类似技术, 例如邮件传输代理的 Mail Transfer Agent Strict Transport Security (MTA-STS) [RFC8461], 以及 SMTP [RFC7672] 和 XMPP [RFC7712] 中基于 DNS-Based Authentication of Named Entities (DANE) [RFC6698] 的方法.
理由: 混合未保护通信和 TLS 保护通信会为 SSL Stripping 及类似攻击打开空间, 因为通信初始部分未受完整性保护, 攻击者可操纵它以使通信保持明文.
3.3. 压缩 (Compression)
使用 TLS 1.2 时, 为帮助防止压缩相关攻击, 见 [RFC7457] 第 2.6 节总结, 实现和部署不应支持 TLS 层压缩 [RFC5246] 第 6.2.2 节.唯一例外是相关应用协议已被证明不会遭受此类攻击.即便如此, 仍需格外谨慎, 因为未来可能出现与 TLS 压缩相关的攻击.更具体地说, HTTP 协议已知易受压缩相关攻击影响.该建议仅适用于 TLS 1.2, 因为 TLS 1.3 已移除压缩.
理由: TLS 压缩曾遭受 Compression Ratio Info-leak Made Easy (CRIME) 等安全攻击.
实现者应注意, 更高协议层的压缩可能允许主动攻击者从连接中提取明文信息.Browser Reconnaissance and Exfiltration via Adaptive Compression of Hypertext (BREACH) 攻击就是这种情况.这些问题只能在 TLS 之外缓解, 因而不在本文范围内.更多细节见 [RFC7457] 第 2.6 节.
3.3.1. 证书压缩 (Certificate Compression)
证书链经常占据握手期间传输字节的大部分.为了控制其大小, 可以使用以下部分或全部方法, 另见 [RFC9191] 第 4 节:
-
限制名称或扩展数量.
-
使用公钥表示较小的密钥, 例如椭圆曲线数字签名算法 (ECDSA).
-
使用证书压缩.
为实现证书压缩, TLS 1.3 在 [RFC8879] 中定义了 compress_certificate 扩展.其安全和隐私考虑见 [RFC8879] 第 5 节.为避免歧义, 针对 TLS 压缩的 CRIME 风格攻击不适用于证书压缩.
由于中间盒干扰的可能性很高, [RFC8879] 风格的压缩没有被提供给 TLS 1.2.理论上可以使用 [RFC7924] 定义的 cached_info 扩展, 但它支持不够广泛, 不能视为实用替代方案.
3.4. TLS 会话恢复 (TLS Session Resumption)
会话恢复大幅减少完整 TLS 握手次数, 因而是多数部署中的关键性能特性.
使用会话票据的无状态会话恢复是一种常见策略.TLS 1.2 中该机制由 [RFC5077] 规定.TLS 1.3 中, 第 4.6.1 节 [RFC8446] 描述了基于预共享密钥 (PSK) 的更安全机制.关于 TLS 加密 "捷径", 包括会话恢复, 所引入风险的定量研究见 [Springall16].
使用会话恢复时, 恢复信息必须经过认证和加密, 以防攻击者修改或窃听.会话票据还适用以下建议:
-
加密票据时必须使用强密码, 至少与主 TLS 密码套件一样强.
-
票据加密密钥必须定期更换, 例如每周一次, 以免抵消前向保密的收益, 见第 7.3 节.旧票据加密密钥必须在有效期结束时销毁.
-
出于类似原因, 会话票据有效期必须限制在合理时长内, 例如为票据加密密钥有效期的一半.
-
TLS 1.2 不会在单个会话内前滚会话密钥.因此, 为防止服务器票据加密密钥被窃取后用于解密整个会话内容, 从而抵消前向保密, TLS 1.2 服务器不应恢复过旧会话, 例如已打开超过两个票据加密密钥轮换周期的会话.
理由: 会话恢复是另一种 TLS 握手, 因而必须与初始握手同样安全.本文第 4 节建议使用提供前向保密的密码套件, 即防止攻击者在短暂访问 TLS 端点及其秘密后读取过去或未来通信.票据必须被正确管理, 以免抵消这种安全属性.
TLS 1.3 提供了强大选项, 可让定期恢复的长连接中也具有前向保密.[RFC8446] 第 2.2 节建议客户端在发起会话恢复时应发送 "key_share".为获得前向保密, 本文建议服务器实现应选择 "psk_dhe_ke" PSK 密钥交换模式, 并以 "key_share" 响应, 在每次会话恢复时完成临时椭圆曲线 Diffie-Hellman (ECDHE) 交换.作为更高性能的替代方案, 服务器实现可以等到自上次 ECDHE 交换以来经过一定时间, 例如按小时计, 再响应 "key_share".这意味着大多数会话恢复请求, 通常发生在数小时内, 不会执行 "key_share" 操作, 同时仍能为较长寿命会话确保前向保密.
TLS 会话恢复会引入潜在隐私问题, 服务器可能借此跟踪客户端, 某些情况下甚至无限期跟踪.详见 [Sy2018].
3.5. TLS 1.2 中的重新协商 (Renegotiation in TLS 1.2)
本节建议仅适用于 TLS 1.2, 因为 TLS 1.3 已移除重新协商.
TLS 1.2 中的重新协商是一种握手, 用于为已有会话建立新的加密参数.该机制存在于 TLS 1.2 和更早协议版本中, 并在包括明文注入攻击 CVE-2009-3555 [CVE] 在内的多次重大攻击后得到改进.
TLS 1.2 客户端和服务器必须实现 [RFC5746] 中定义的 renegotiation_info 扩展.
TLS 1.2 客户端必须在 Client Hello 中发送 renegotiation_info.如果服务器未确认该扩展, 客户端必须在终止连接前生成致命 handshake_failure 警报.
理由: 无论任一端点是否实际实现重新协商, 客户端连接到不支持 renegotiation_info 的 TLS 1.2 服务器都是不安全的.另见 [RFC5746] 第 4.1 节.
由 TLS 会话参数未被正确认证引发的相关攻击是 Triple Handshake [Triple-Handshake].为处理该攻击, TLS 1.2 实现必须支持 [RFC7627] 定义的 extended_master_secret 扩展.
3.6. 握手后认证 (Post-Handshake Authentication)
TLS 1.2 中的重新协商在 TLS 1.3 中由独立的握手后认证和密钥更新机制部分替代.在单个连接上复用请求的协议, 例如 HTTP/2 [RFC9113], 中, 握手后认证具有与 TLS 1.2 重新协商相同的问题.复用协议应遵循 [RFC9113] 第 9.2.3 节对 HTTP/2 给出的建议.
3.7. 服务器名称指示 (Server Name Indication, SNI)
对于会从 SNI 受益的高层协议, 包括 HTTPS, TLS 实现必须支持 [RFC6066] 第 3 节定义的服务器名称指示 (SNI) 扩展.不过, 在特定场景中是否实际使用 SNI 属于本地策略.撰写本文时, TLS 工作组正在制定一种加密 SNI 的技术, 称为 Encrypted Client Hello [TLS-ECH].一旦该方法标准化并广泛实现, 未来版本的本 BCP 可能适合推荐使用它.
理由: SNI 支持在单个地址上部署多个受 TLS 保护的虚拟服务器, 并通过允许每个虚拟服务器拥有自己的证书, 为这些虚拟服务器启用细粒度安全.不过, SNI 也会泄露给定连接的目标域.TLS Encrypted Client Hello 标准化后, 这种信息泄露将被消除.
为防止 [ALPACA] 中描述的攻击, 服务器如果不识别呈现的服务器名称, 不应继续握手, 而应使用致命级 unrecognized_name(112) 警报失败.注意, 该建议更新了 [RFC6066] 第 3 节中的说法: 如果服务器理解 ClientHello 扩展但不识别服务器名称, 服务器应选择两种动作之一, 即发送致命级 unrecognized_name(112) 警报中止握手, 或继续握手.
如果服务器确认了 SNI 扩展, 但呈现的证书主机名不同于客户端发送的主机名, 客户端应中止握手.
3.8. 应用层协议协商 (Application-Layer Protocol Negotiation, ALPN)
TLS 实现, 包括客户端和服务器端, 必须支持应用层协议协商 (ALPN) 扩展 [RFC7301].
为防止因未确保某个协议中的消息不会被误认为另一个协议中的消息而导致的 "跨协议" 攻击, 建议服务器严格执行 [RFC7301] 第 3.2 节规定的行为: 如果服务器不支持客户端通告的任何协议, 服务器应以致命 no_application_protocol 警报响应.
如果服务器确认 ALPN 扩展但未从客户端列表中选择协议, 客户端应中止握手.否则可能导致 [ALPACA] 中描述的攻击.
强烈鼓励协议开发者为其协议注册 ALPN 标识符.该建议同时适用于新协议和成熟协议.不过, 对于后者, 由于可能已有大量部署, 在为成熟协议注册 ALPN 标识符时, 严格强制使用 ALPN 可能不可行.
3.9. 多服务器部署 (Multi-Server Deployment)
涉及多个服务器或服务的部署可能增大 TLS 攻击面.需要关注两类场景:
-
多个服务通过不同协议处理同一域名, 例如 HTTP 和 IMAP.在这种情况下, 攻击者可能把连接端点引导到提供不同协议的服务, 并发动跨协议攻击.跨协议攻击中, 客户端和服务器认为自己正在使用不同协议, 如果某一协议发送的消息在另一协议中被解释为具有不良效果的消息, 攻击者就可能利用这种情况.关于此类攻击的更多信息见 [ALPACA].为缓解该威胁, 服务提供者应部署 ALPN, 见第 3.8 节.此外, 在可能范围内, 他们应确保处理同一域名的多个服务提供等价安全级别, 且与本文建议一致.这些措施应包括跨多个 TLS 服务器处理配置, 以及保护这些服务器持有的凭据不被攻陷.
-
提供同一服务的多个服务器具有不同 TLS 配置.在这种情况下, 攻击者可能把连接端点引导到 TLS 配置更容易被利用的服务器, 关于此类攻击见 [DROWN].为缓解该威胁, 服务提供者应确保提供同一服务的所有服务器提供等价安全级别, 且与本文建议一致.
3.10. TLS 1.3 中的零往返时间 (0-RTT) 数据 (Zero Round-Trip Time Data)
0-RTT 早期数据是 TLS 1.3 中的新特性.它在恢复 TLS 连接时降低延迟, 代价是可能损失某些安全属性.因此, 服务器端和客户端实现者都需要特别关注.通常, 这不仅涉及 TLS 库, 也涉及其上的协议层.
HTTP over TLS 的指导见 [RFC8470].
QUIC over TLS 的指导见 [RFC9001] 第 9.2 节.
对其他协议, 通用指导见 [RFC8446] 第 8 节和附录 E.5.概括附录 E.5 的意思, 除非相关应用协议有明确规范说明何时使用 0-RTT 是适当且安全的, 否则应用必须避免使用该特性.该规范可以是 IETF RFC、非 IETF 标准, 或与非标准协议关联的文档.