9. 安全考虑 (Security Considerations)
本节旨在告知开发人员、信息提供者和用户与HTTP语义及其用于在互联网上传输信息相关的已知安全问题。与消息语法、解析和路由相关的考虑在[RFC7230]中讨论,与HTTP缓存相关的考虑在[RFC7234]中讨论。
下面的考虑列表并非详尽无遗。与HTTP语义相关的大多数安全问题涉及保护服务器端应用程序(HTTP接口后面的代码)、保护用户代理处理通过HTTP接收的内容,或安全使用从HTTP头字段获得的信息。这些问题中的许多是相互依赖的;客户端软件中的弱点可以用来利用服务器软件中的漏洞,反之亦然。
9.1. 基于文件和路径名的攻击 (Attacks Based on File and Path Names)
源服务器经常使用其本地文件系统来管理从目标URI到资源表示的映射。大多数文件系统并非设计为防止恶意文件或路径名。因此,源服务器在将目标资源映射到文件、文件夹或目录时,需要避免访问对系统具有特殊意义的名称。
例如,UNIX、Microsoft Windows和其他操作系统使用".."作为路径组件来指示当前目录的上一级目录,并且它们使用特殊命名的路径或文件名将数据发送到系统设备。在其他类型的存储系统中可能存在类似的命名约定。同样,本地存储系统在处理无效或意外字符时有一种令人讨厌的倾向,即更倾向于用户友好性而非安全性,以可能导致意外模式的方式重新组合它们。
实现需要小心,不要对同一字符串进行多次转义或反转义,因为对先前转义的字符串进行反转义可能导致不安全的字符。特别是,简单地对请求目标进行反转义并在没有额外检查的情况下将其用作文件系统路径是不安全的。
请注意,本规范中对目标URI的限制不足以防止这些类型的攻击;它们必须由实现特定的检查来补充。
9.2. 基于命令、代码或查询注入的攻击 (Attacks Based on Command, Code, or Query Injection)
源服务器通常使用URI中的参数作为识别系统服务、选择数据库条目或选择数据源的手段。但是,请求中接收的数据不能被信任。攻击者可以构造任何请求数据元素(方法、请求目标、头字段或主体),以包含在通过命令调用、语言解释器或数据库接口传递时可能被误解为命令、代码或查询的数据。
例如,SQL注入是一种常见的攻击,其中在请求目标或头字段(例如Host、Referer等)的某些部分中插入额外的查询语言。如果接收的数据直接在SQL SELECT语句中使用,查询语言可能被解释为数据库命令而不是简单的字符串值。尽管这种类型的实现漏洞很容易防止,但它极其常见。
一般来说,资源实现应该(ought to)避免在组装shell命令或查询时使用请求数据。当此类使用是必要的时,数据在使用前需要被适当转义(适合接收数据的系统)。
9.3. 个人信息泄露 (Disclosure of Personal Information)
客户端通常知道大量个人信息,包括用户提供的用于与资源交互的信息(例如,用户的姓名、位置、邮件地址、密码、加密密钥等)以及关于用户随时间浏览活动的信息(例如,历史记录、书签等)。实现需要防止此类信息的无意泄露。
9.3.1. 通过应用程序数据泄露 (Disclosure via Application Data)
应用程序应该(ought to)将其信息披露限制在完成请求所需的范围内,并避免披露特定于用户或应用程序内部结构的信息(第5.5.3节和第7.4.2节)。
9.3.2. 通过Referer泄露 (Disclosure via Referer)
Referer头字段允许客户端向服务器宣传客户端获取请求目标的位置,这可能揭示有关用户上下文或浏览历史的信息。在请求目标由第三方来源提供的情况下,用户可能希望保持该信息的机密性(例如,来自医疗信息的链接)。因此,用户代理应该(ought to)为用户提供不发送Referer字段的选项,或发送该字段的较少揭示性(例如,仅原点)版本(第5.5.2节)。
如果引用页面是使用安全协议接收的,客户端不应该(ought not to)在(非安全)HTTP请求中包含Referer头字段。
使用HTTP协议的服务的作者不应该(ought not to)使用带有表单编码内容的GET和POST请求来传输敏感信息,例如个人识别信息、账号、密码等,因为这会导致该数据未加密并在请求目标或内容中传输。服务设计者应该(ought to)使用带有消息主体的POST方法来传输此类敏感信息,注意不要在请求目标中包含此类信息,因为这可能在日志、书签等中暴露。
9.3.3. 通过User-Agent泄露 (Disclosure via User-Agent)
User-Agent头字段通常包含足够的信息来唯一标识特定设备,特别是当与其他特征结合时,尤其是如果用户代理发送关于用户系统或扩展的过多细节。实现应该(ought to)限制此类信息(第5.5.3节)。
9.4. 服务器日志信息的隐私 (Privacy of Server Log Information)
服务器能够保存关于用户随时间请求的个人数据,这可能识别他们的阅读模式或感兴趣的主题。特别是,在中介处收集的日志信息通常包含跨多个站点的用户代理交互历史,可以追溯到个别用户。
HTTP日志信息本质上是机密的;其处理通常受法律和法规的约束。日志信息需要安全存储,并遵循适当的分析指南。对单个条目中的个人信息进行匿名化有所帮助,但通常不足以防止真实的日志跟踪基于与其他访问特征的关联而被重新识别。因此,与特定客户端关联的访问跟踪应该(ought to)被匿名化或被视为机密。
为了最小化盗窃或意外发布的风险,日志信息应该(ought to)尽快清除。
9.5. 重定向后的片段泄露 (Disclosure of Fragment after Redirects)
尽管在URI引用中使用的片段标识符不会在请求中发送,但实现者应该(ought to)意识到它们将对用户代理以及作为响应结果运行的任何扩展或脚本可见。特别是,当发生重定向并且原始请求的片段标识符被Location中的新引用继承时(第7.1.2节),这可能具有安全后果。
9.6. 产品信息泄露 (Disclosure of Product Information)
Server和User-Agent头字段通常揭示有关各自发送者的软件系统的信息。理论上,这可以使攻击者更容易利用已知的安全漏洞;实际上,无论使用的软件版本如何,攻击者往往会尝试所有潜在的漏洞。
作为网络防火墙门户的代理应该(ought to)对可能识别防火墙后面主机的头信息的传输采取特殊预防措施。Via头字段允许中介用假名替换敏感的机器名称。
9.7. 浏览器指纹识别 (Browser Fingerprinting)
浏览器指纹识别是一组技术,用于通过其独特的特征集随时间识别特定用户代理。这些特征可能包括与其如何使用底层传输协议、功能能力和脚本环境相关的信息,尽管这里特别感兴趣的是可能通过HTTP通信的独特特征集。指纹识别被认为是隐私问题,因为它使得能够随时间跟踪用户代理的行为(第9.4节),而用户可能无法对其他形式的数据(如cookie)进行相应控制。
有许多请求头字段可能向服务器揭示足够独特的信息以启用指纹识别。From头字段是最明显的,尽管预期From仅在用户希望自我识别时发送。同样,Cookie头字段被故意设计为启用重新识别,因此指纹识别问题仅在用户代理禁用或限制cookie时适用。
User-Agent头字段可能包含足够的信息来唯一标识特定设备,通常当与其他特征结合时,特别是如果用户代理发送关于用户系统或扩展的过多细节。然而,用户最不期望的独特信息来源是主动协商(第3.4.1节),包括Accept、Accept-Charset、Accept-Encoding和Accept-Language头字段。
除了指纹识别问题外,Accept-Language头字段的详细使用可能揭示用户可能认为是私人性质的信息。例如,理解给定的语言集可能与特定种族群体的成员身份强相关。限制这种隐私损失的方法是用户代理省略发送Accept-Language,除非是已被列入白名单的站点,也许是在检测到指示语言协商可能有用的Vary头字段后通过交互。
在使用代理来增强隐私的环境中,用户代理应该(ought to)在发送主动协商头字段时保守。提供高度头字段可配置性的通用用户代理应该(ought to)告知用户如果提供太多细节可能导致的隐私损失。作为极端的隐私措施,代理可以在中继请求中过滤主动协商头字段。
9.8. 验证器保留 (Validator Retention)
响应元数据(第7.2节)中包含的验证器应该(ought to)仅由缓存保留,只要对缓存响应的正常处理和过期所需的时间。长期保留验证器可能导致隐私问题,因为旧的验证器可能用于关联单个用户跨多个请求的活动,即使服务器没有明确地将验证器值与个别用户关联。不作为缓存的用户代理不应该(ought not to)长期保留验证器。