Gecko 中的 Web 安全检查

关键概念和术语

安全主体 (nsIPrincipal)

安全主体代表代码或数据的安全上下文。Firefox 使用四种类型的安全主体

  • 内容主体 (ContentPrincipal):用于典型的网页,可以序列化为源 URL,例如 https://example.com/

  • 空主体 (NullPrincipal):用于永远不会与其他任何内容同源的页面,例如具有 sandbox 属性的 iframe 或使用 data: URI 加载的文档。这也被称为不透明源。

  • 系统主体 (SystemPrincipal):用于浏览器的用户界面(通常称为“浏览器 chrome”)以及各种其他后台服务(OCSP 请求、获取网站图标)。像 about:preferences 这样的页面使用系统主体。

  • 扩展主体 (ExpandedPrincipal):由需要假定网站安全上下文的浏览器扩展使用。扩展主体最好理解为一个主体列表。

OriginAttributes

OriginAttributes 通过区分可能基于其主体被视为相同的不同安全上下文来帮助管理和执行安全策略。它们用于

  • 隔离私密浏览模式下的数据和资源。

  • 实现缓存隔离。

  • 管理容器标签的用户上下文标识符。

  • 执行第一方隔离。

属性

OriginAttributes 类扩展了 dom::OriginAttributesDictionary 的功能,并包括用于设置和管理各种属性的其他方法。

关键属性包括

  • FirstPartyDomain:用于根据域隔离数据。

  • UserContextId:标识不同的用户上下文,例如容器标签。

  • PrivateBrowsingId:指示请求是否在私密浏览模式下发出。

  • PartitionKey:用于实现缓存隔离。

加载信息对象 (nsILoadInfo)

nsILoadInfo 对象对于安全检查至关重要。它包含所有与安全相关的属性,包括指示需要执行哪些检查的安全标志以及关联的主体。

属性:

  • loadingPrincipal:加载结果将在其中使用的文档的主体。

  • triggeringPrincipal:触发 URL 加载的主体。

  • securityFlags:指示所需的安全性检查类型。

  • contentPolicyType:指定正在加载的内容类型,用于内容安全策略等安全检查。

Firefox 中的加载生命周期

从请求到响应

  1. 请求发起:网页发起请求。

  2. 创建 nsIChannel:Firefox 创建一个 nsIChannel 对象,表示请求。

  3. 附加 nsILoadInfo:创建 nsIChannel 需要 nsILoadInfo 对象,并包含与安全相关的信息。

  4. 安全检查:使用 ContentSecurityManager 执行安全检查。

  5. 执行请求:如果所有检查都通过,则请求继续。

nsIChannel 和 nsILoadInfo 的作用

  • nsIChannel:管理传输算法(例如,HTTP、WebSocket)。

  • nsILoadInfo:保存网络加载的安全相关元信息,并确定需要执行哪些安全检查。

加载过程中的安全检查

请求前检查

  • 同源策略:确保仅在资源共享相同源时才能访问资源。

  • 内容安全策略:根据站点定义的策略强制执行内容限制。

  • 混合内容阻止:实现混合内容标准,包括阻止和升级安全(HTTPS)页面上的不安全(HTTP)内容。

ContentSecurityManager 和 doContentSecurityCheck()

  • ContentSecurityManager:执行安全检查的集中式管理器。

  • PerformSecurityCheck():在执行请求之前调用以执行所有相关安全检查的关键函数。

包含概念

  • 定义:如果一个主体可以访问相同的资源,则它包含另一个主体。

  • 实现aPrincipal->Subsumes(aOtherPrincipal) 用于检查访问权限。

代码示例

bool subsumes = principal1->Subsumes(principal2);

包含是不对称的。一个主体包含另一个主体并不意味着反过来也成立。一个典型的例子是 SystemPrincipal,它包含所有其他主体。

参考

源代码中的接口定义有很多详细的注释