跳到主要内容

9. 安全考量

本节旨在告知开发者、信息提供者和用户: 与 HTTP 消息语法、解析和路由相关的已知安全考量. 关于 HTTP 语义和载荷的安全考量在 [RFC7231] 中讨论.

9.1. 确立权威​

HTTP 依赖 "权威响应" (authoritative response) 这一概念: 它是指由目标 URI 中标识的权威 (或按该权威的指示) 所确定的、在响应消息生成时依据目标资源的状态而对该请求最为适当的响应. 从非权威来源 (例如共享缓存) 提供响应, 通常有利于提升性能和可用性, 但仅限于该来源可信, 或者该不可信响应可以被安全使用的程度.

不幸的是, 确立权威可能很困难. 例如, 钓鱼 (phishing) 就是针对用户对权威的感知发起的攻击: 通过在超文本中呈现相似的品牌标识, 并且可能借助 userinfo 来混淆 authority 分量 (见第 2.7.1 节), 从而误导这种感知. 用户代理可以减轻钓鱼攻击的影响, 做法是让用户能在采取动作之前轻松查看目标 URI、在有 userinfo 时显著区分 (或拒绝) 它, 以及在引用文档来自未知或不受信任来源时不发送已存储的凭证和 cookie.

当 authority 分量中使用注册名时, "http" URI 方案 (第 2.7.1 节) 依赖用户本地的名称解析服务来确定何处可以找到权威响应. 这意味着对用户的网络主机表、缓存名称或名称解析库的任何攻击, 都会成为攻击 "确立权威" 的途径. 同样, 用户对域名服务 (Domain Name Service, DNS) 服务器的选择, 以及它从中获得解析结果的服务器层级, 都可能影响地址映射的真实性; DNS 安全扩展 (DNS Security Extensions, DNSSEC, [RFC4033]) 是提升真实性的一种途径.

此外, 在获得 IP 地址之后, 为 "http" URI 确立权威还会受到对 Internet Protocol 路由的攻击的影响.

"https" 方案 (第 2.7.2 节) 的意图是防止 (或至少揭示) 上述许多针对 "确立权威" 的潜在攻击, 前提是协商出的 TLS 连接受到保护, 并且客户端正确验证通信服务器的身份与目标 URI 的 authority 分量相符 (见 [RFC2818]). 正确实现这种验证可能很困难 (见 [Georgiev]).

9.2. 中间方的风险​

就其本质而言, HTTP 中间方是中间人, 因此构成了实施中间人攻击的机会. 中间方所运行的系统被攻陷, 可能导致严重的安全和隐私问题. 中间方可能能够访问与安全相关的信息、关于单个用户和组织的个人信息, 以及属于用户和内容提供者的专有信息. 被攻陷的中间方, 或者在实现或配置时未考虑安全和隐私的中间方, 可能被用于实施各种潜在攻击.

包含共享缓存的中间方尤其容易受到缓存投毒攻击, 如 [RFC7234] 第 8 节所述.

实现者需要考虑其设计和编码决策所带来的隐私与安全影响, 以及他们提供给运维人员的配置选项 (尤其是默认配置) 所带来的影响.

用户需要意识到: 中间方的可信程度不会高于运行它们的人; HTTP 本身无法解决这个问题.

9.3. 通过协议元素长度发起的攻击​

由于 HTTP 主要使用文本型、以字符分隔的字段, 解析器往往容易受到基于发送极长 (或极慢) 数据流的攻击, 尤其是在实现所期望的协议元素长度未预先定义时.

为促进互操作性, 针对 request-line (第 3.1.1 节) 和头部字段 (第 3.2 节) 的最小长度限制作出了具体建议. 这些是最低建议, 其选取标准是即使资源有限的实现也能支持; 可以预期大多数实现会选择明显更高的限制.

服务器可以拒绝请求目标过长的消息 ([RFC7231] 第 6.5.12 节) 或者请求载荷过大的消息 ([RFC7231] 第 6.5.11 节). 与容量限制相关的其他状态码已由 HTTP 的扩展 [RFC6585] 定义.

接收方应当谨慎限制其处理其他协议元素的程度, 包括 (但不限于) 请求方法、响应原因短语、头部字段名、数值和主体块. 未能限制这类处理可能导致缓冲区溢出、算术溢出, 或者增加对拒绝服务攻击的脆弱性.

9.4. 响应分裂​

响应分裂 (response splitting, 又称 CRLF 注入) 是对 Web 使用的各种攻击中常用的一种技术, 它利用 HTTP 消息分帧基于行的特性, 以及持久连接上请求与响应按顺序关联的特性 [Klein]. 当请求经过共享缓存时, 这种技术可能尤其具有破坏性.

响应分裂利用服务器 (通常是应用服务器内部) 的一个漏洞: 攻击者可以在请求的某个参数中发送编码数据, 该数据随后被解码并在响应的任一响应头部字段中被回显. 如果解码后的数据被构造得看起来像 "响应已结束、后续响应已开始", 那么该响应就被分裂了, 而表面上第二个响应的内容由攻击者控制. 攻击者随后可以在同一条持久连接上发出任何其他请求, 并诱使接收方 (包括中间方) 相信该分裂的后半部分是第二个请求的权威应答.

例如, 请求目标中的某个参数可能被应用服务器读取并在重定向中复用, 从而导致该参数被回显在响应的 Location 头部字段中. 如果该参数被应用解码, 而在放入响应字段时没有被正确编码, 那么攻击者就可以发送编码的 CRLF 八位组和其他内容, 使应用的单条响应看起来像是两条或更多条响应.

防范响应分裂的一种常见做法是过滤请求中形似编码 CR 和 LF 的数据 (例如 "%0D" 和 "%0A"). 然而, 这假定应用服务器只进行 URI 解码, 而不做更隐晦的数据变换, 例如字符集转码、XML 实体转换、base64 解码、sprintf 重格式化等. 一种更有效的缓解措施是: 除服务器核心协议库之外, 阻止任何其他组件在头部部分内发送 CR 或 LF; 这意味着把头部字段的输出限制在经过坏八位组过滤的 API 上, 并且不允许应用服务器直接写入协议流.

9.5. 请求走私​

请求走私 (request smuggling, [Linhart]) 是一种利用各接收方在协议解析上的差异, 把额外请求 (这些请求本可能被策略阻断或禁用) 隐藏在一个看似无害的请求之内的技术. 与响应分裂一样, 请求走私可能导致针对 HTTP 使用的各种攻击.

本规范对请求解析引入了新的要求, 尤其是在第 3.3.3 节关于消息分帧的要求, 以降低请求走私的有效性.

9.6. 消息完整性​

HTTP 没有定义用于确保消息完整性的特定机制, 而是依赖底层传输协议的差错检测能力, 以及使用长度界定或分块界定的分帧来检测完整性. 附加的完整性机制 (例如施加于内容的散列函数或数字签名) 可以通过可扩展的元数据头部字段有选择地加入消息. 从历史上看, 缺少单一完整性机制的合理性来自大多数 HTTP 通信的非正式性质. 然而, HTTP 作为信息访问机制的普及, 使其越来越多地被用于 "验证消息完整性至关重要" 的环境.

鼓励用户代理实现可配置的手段, 用于检测和报告消息完整性失败, 以便在需要完整性的环境中能够启用这些手段. 例如, 用于查看病史或药物相互作用信息的浏览器, 需要在该信息被协议检测为不完整、已过期或在传输中损坏时向用户指明. 此类机制可以通过用户代理扩展, 或者通过响应中存在消息完整性元数据, 来有选择地启用. 至少, 用户代理应当提供某种指示, 使用户在需要此类验证时能够区分完整的与不完整的响应消息 (第 3.4 节).

9.7. 消息机密性​

在需要消息机密性时, HTTP 依赖底层传输协议来提供. HTTP 被特意设计为与传输协议无关, 从而可以在许多不同形式的加密连接上使用, 而这些传输的选择由 URI 方案的选择或者用户代理配置来指明.

"https" 方案可用于标识需要机密连接的资源, 如第 2.7.2 节所述.

9.8. 服务器日志信息的隐私​

服务器有能力长期保存关于用户请求的个人数据, 这些数据可能识别出用户的阅读模式或感兴趣的主题. 特别是, 在中间方收集的日志信息往往包含用户代理跨众多站点交互的历史, 而这些历史可以追溯到具体用户.

HTTP 日志信息在性质上是机密的; 其处理往往受到法律和法规的约束. 日志信息需要被安全存储, 并在分析时遵循适当的准则. 对单条记录中的个人信息进行匿名化处理有所帮助, 但通常不足以防止真实日志记录基于与其他访问特征的关联而被重新识别. 因此, 与特定客户端绑定的访问记录即使其键是假名的, 也不安全, 不宜发布.

为把被盗或意外公开的风险降到最低, 日志信息应当在其不再为支持安全、审计或欺诈控制等运行需要之后, 尽快清除其中的个人可识别信息, 包括用户标识符、IP 地址和用户提供的查询参数.