{"id":143,"date":"2020-06-10T00:40:25","date_gmt":"2020-06-10T07:40:25","guid":{"rendered":"https:\/\/blog.mozilla.org\/attack-and-defense\/?p=143"},"modified":"2020-06-16T07:24:05","modified_gmt":"2020-06-16T14:24:05","slug":"understanding-web-security-checks-in-firefox-part-1","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/attack-and-defense\/2020\/06\/10\/understanding-web-security-checks-in-firefox-part-1\/","title":{"rendered":"Understanding Web Security Checks in Firefox (Part 1)"},"content":{"rendered":"<div style=\"display:none\"><\/div>\n<p><span style=\"font-weight: 400;\">This is the first part of a blog post series that will allow you to understand how Firefox implements Web Security fundamentals, like the <\/span><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Security\/Same-origin_policy\"><span style=\"font-weight: 400;\">Same-Origin Policy<\/span><\/a><span style=\"font-weight: 400;\">. This first post of the series covers the architectural design, terminology, and introduces core interfaces that our implementation of the Same-Origin Policy relies on: <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/caps\/nsIPrincipal.idl\"><span style=\"font-weight: 400;\">nsIPrincipal<\/span><\/a><span style=\"font-weight: 400;\"> and <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/netwerk\/base\/nsILoadInfo.idl\"><span style=\"font-weight: 400;\">nsILoadinfo<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400;\">Background on Web Security Checks<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Whenever Firefox on Desktop or Android fetches a resource from the web, Firefox performs a variety of web security checks to ensure web pages can not harm end users by performing malicious actions. For example, when loading a sub-resource from a web page, Firefox ensures that its URL is not targeting the local file system with a file:\/\/ scheme. Before diving deeper into Firefox Security internals we have to introduce the term <\/span><i><span style=\"font-weight: 400;\">Security Principal<\/span><\/i><span style=\"font-weight: 400;\">, which is key for understanding how Firefox enforces web security checks.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400;\">The Security Contexts in Firefox<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">All web related security checks within Firefox are evaluated based on the security concept of a Principal. Briefly, a Principal reflects a security context. E.g., when visiting https:\/\/example.com a <\/span><i><span style=\"font-weight: 400;\">Content-Principal<\/span><\/i><span style=\"font-weight: 400;\"> of https:\/\/example.com reflects the security context of that page. More precisely, Firefox captures the security context using one of the following four types of Principals:<\/span><\/p>\n<ol>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>Content-Principal<\/strong><br \/>\n<\/span><span style=\"font-weight: 400;\">The <\/span><a href=\"https:\/\/html.spec.whatwg.org\/multipage\/origin.html\"><span style=\"font-weight: 400;\">HTML specification<\/span><\/a><span style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"> associates an origin with a Document or a Worker. That origin information is encapsulated within a Content-Principal and reflects the security context for all web-hosted resources. E.g. when loading the web page https:\/\/example.com, then Firefox creates a Content-Principal encapsulating origin information of https:\/\/example.com which then reflects the security context of that web page.<\/span><\/span><\/li>\n<li><strong>Null-Principal<\/strong><br \/>\n<span style=\"font-weight: 400;\">In special cases, websites are never same-origin with anything else. Two such cases are iframes with a sandbox attribute and documents loaded with a data: URI. The HTML specification calls the origin of those pages an <\/span><a href=\"https:\/\/html.spec.whatwg.org\/multipage\/origin.html#concept-origin-opaque\"><span style=\"font-weight: 400;\">opaque origin<\/span><\/a><span style=\"font-weight: 400;\">. Our implementation uses a\u00a0 <\/span><i><span style=\"font-weight: 400;\">Null-Principal<\/span><\/i><span style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"> for reflecting the security context of an opaque origin. In contrast to a Content-Principal which internally maps to the origin of the resource, a Null-Principal uses a custom scheme and host, e.g. moz-nullprincipal:{0bceda9f-&#8230;}, where the host is represented as a UUID. So, when loading an iframe with a sandbox attribute Firefox internally generates a Null-Principal to reflect that security context. Please note that a Null-Principal is not equal to any other Principal and also not equal to any other Null-Principal. E.g., a data: URI iframe is not same-origin with another data: URI iframe because both security contexts are mapped through different Null-Principals.<\/span><\/span><\/li>\n<li><span style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>System-Principal<\/strong><br \/>\nThe <i>System-Principal<\/i> is used for the browser\u2019s user interface, commonly referred to as \u201cbrowser chrome\u201d. An example of a page with these extra privileges is \u201cabout:support\u201d. The System-Principal is shared across all privileged resources, and implemented as a Singleton. Since browser chrome code does not rely on a URI, the System-Principal internally also does not map to an origin. The System-Principal passes all security checks.<\/span><\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><strong>Expanded-Principal<\/strong><br \/>\nA browser extension is more privileged than normal web pages, but must also be able to assume the security context of a website. Hence, an <i>Expanded-Principal<\/i> is best understood as a <i>list of principals<\/i> to match the security needs for <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Mozilla\/Add-ons\/WebExtensions\/Anatomy_of_a_WebExtension#Content_scripts\">Content Scripts<\/a> in Firefox Extensions. When creating an Expanded-Principal Firefox takes multiple existing Principals, storing them in an allowlist. The security checks on the Expanded-Principal are then implemented as a loop through this allowlist of principals.<\/span><\/li>\n<\/ol>\n<h2><span style=\"font-weight: 400;\"><br \/>\nThe Loading Life-Cycle in Firefox<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Whenever a page performs a request, Firefox internally creates an <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/netwerk\/base\/nsIChannel.idl\"><span style=\"font-weight: 400;\">nsIChannel<\/span><\/a><span style=\"font-weight: 400;\"> object (which acts as the transport algorithm, such as HTTP(S), WebSocket etc.). Amongst other things an <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/netwerk\/base\/nsIChannel.idl\"><span style=\"font-weight: 400;\">nsIChannel<\/span><\/a><span style=\"font-weight: 400;\"> consists of an <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/netwerk\/base\/nsIURI.idl\"><span style=\"font-weight: 400;\">nsIURI<\/span><\/a><span style=\"font-weight: 400;\">, which is the URI to be loaded, and an <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/netwerk\/base\/nsILoadInfo.idl\"><span style=\"font-weight: 400;\">nsILoadInfo<\/span><\/a><span style=\"font-weight: 400;\"> object. The latter holds all security relevant attributes including security flags indicating what security checks need to be performed and the aforementioned Principal. It is worth emphasizing that the loadinfo &#8211; including the Principal &#8211; gets frozen at creation time and remains attached to the <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/netwerk\/base\/nsIChannel.idl\"><span style=\"font-weight: 400;\">nsIChannel<\/span><\/a><span style=\"font-weight: 400;\"> instance even if the load encounters any kind of redirect, e.g. a 302. The last step before Firefox starts loading bits over the network is performing all relevant security checks within the function <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/rev\/501eb4718d73870892d28f31a99b46f4783efaa0\/netwerk\/base\/nsIChannel.idl#189\"><span style=\"font-weight: 400;\">asyncOpen()<\/span><\/a><span style=\"font-weight: 400;\"> of any <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/netwerk\/base\/nsIChannel.idl\"><span style=\"font-weight: 400;\">nsIChannel<\/span><\/a><span style=\"font-weight: 400;\"> implementation.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400;\">Enforcing Web Security Checks in Firefox<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Firefox enforces all <\/span><a href=\"https:\/\/blog.mozilla.org\/security\/2016\/11\/10\/enforcing-content-security-by-default-within-firefox\/\"><span style=\"font-weight: 400;\">web security checks by default<\/span><\/a><span style=\"font-weight: 400;\"> by consulting a centralized <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/source\/dom\/security\/nsContentSecurityManager.cpp\"><span style=\"font-weight: 400;\">ContentSecurityManager<\/span><\/a><span style=\"font-weight: 400;\">. As mentioned, every <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/rev\/501eb4718d73870892d28f31a99b46f4783efaa0\/netwerk\/base\/nsIChannel.idl#189\"><span style=\"font-weight: 400;\">asyncOpen()<\/span><\/a><span style=\"font-weight: 400;\"> implementation internally calls <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/rev\/501eb4718d73870892d28f31a99b46f4783efaa0\/dom\/security\/nsContentSecurityManager.cpp#940\"><span style=\"font-weight: 400;\">doContentSecurityCheck()<\/span><\/a><span style=\"font-weight: 400;\"> which then performs all relevant web security checks e.g., <\/span><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Security\/Same-origin_policy\"><span style=\"font-weight: 400;\">Same-Origin Policy<\/span><\/a><span style=\"font-weight: 400;\">, <\/span><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/CSP\"><span style=\"font-weight: 400;\">Content Security Policy<\/span><\/a><span style=\"font-weight: 400;\">, <\/span><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Security\/Mixed_content\"><span style=\"font-weight: 400;\">Mixed Content Blocking<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To perform all relevant security checks Firefox has to take <\/span><i><span style=\"font-weight: 400;\">multiple<\/span><\/i><span style=\"font-weight: 400;\"> principals into consideration, most notably the <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/rev\/501eb4718d73870892d28f31a99b46f4783efaa0\/netwerk\/base\/nsILoadInfo.idl#254\"><span style=\"font-weight: 400;\">loadingPrincipal<\/span><\/a><span style=\"font-weight: 400;\"> and the <\/span><a href=\"https:\/\/searchfox.org\/mozilla-central\/rev\/501eb4718d73870892d28f31a99b46f4783efaa0\/netwerk\/base\/nsILoadInfo.idl#304\"><span style=\"font-weight: 400;\">triggeringPrincipal<\/span><\/a><span style=\"font-weight: 400;\">.\u00a0 The <\/span><span style=\"font-weight: 400;\">loadingPrincipal<\/span><span style=\"font-weight: 400;\"> is the principal of the document where the result of the load will be used. The <\/span><span style=\"font-weight: 400;\">triggeringPrincipal<\/span><span style=\"font-weight: 400;\"> is the security context that actually triggered the URL to load. In most cases the loadingPrincipal and the triggeringPrincipal are identical. One example where loadingPrincipal and triggeringPrincipal differ is a cross-origin CSS file requesting an image. In that case the loadingPrincipal is a Content-Principal of the page where the image will be loaded into, and the triggeringPrincipal is a cross-origin Content-Principal of the CSS file.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Taking the loadingPrincipal and the triggeringPrincipal into account, Firefox performs security checks in an <\/span><i><span style=\"font-weight: 400;\">asymmetric <\/span><\/i><span style=\"font-weight: 400;\">fashion. More precisely, a Principal may have access to another Principal but not necessarily vice versa. This is also why security checks are not implemented as equality checks. Instead, Firefox relies on the concept of \u2018subsumes\u2019. In more detail, Firefox uses <\/span><span style=\"font-weight: 400;\">aPrincipal-&gt;Subsumes(aOtherPrincipal)<\/span><span style=\"font-weight: 400;\">, to see if<\/span><span style=\"font-weight: 400;\"> aPrincipal <\/span><span style=\"font-weight: 400;\">has access to <\/span><span style=\"font-weight: 400;\">aOtherPrincipal<\/span><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">The aforementioned System-Principal subsumes all other principals, but a Null-Principal basically fails all security checks and is only same-origin with itself. A Content-Principal is same- origin to another Content-Principal if <\/span><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/Security\/Same-origin_policy\"><span style=\"font-weight: 400;\">scheme, host and port<\/span><\/a><span style=\"font-weight: 400;\"> are the same for both. If so, Firefox allows the load.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400;\">An illustrative example of a Web Security Check<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">Let\u2019s assume you visit the web page https:\/\/example.com and that page then loads library.js from https:\/\/foo.com. For the JavaScript load to occur Firefox will internally create an nsIChannel with the URL of https:\/\/foo.com\/library.js.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter wp-image-144 size-large\" src=\"http:\/\/blog.mozilla.org\/attack-and-defense\/files\/2020\/06\/sec_by_default-600x426.jpg\" alt=\"\" width=\"600\" height=\"426\" srcset=\"https:\/\/blog.mozilla.org\/attack-and-defense\/files\/2020\/06\/sec_by_default-600x426.jpg 600w, https:\/\/blog.mozilla.org\/attack-and-defense\/files\/2020\/06\/sec_by_default-300x213.jpg 300w, https:\/\/blog.mozilla.org\/attack-and-defense\/files\/2020\/06\/sec_by_default-768x545.jpg 768w, https:\/\/blog.mozilla.org\/attack-and-defense\/files\/2020\/06\/sec_by_default-1000x710.jpg 1000w, https:\/\/blog.mozilla.org\/attack-and-defense\/files\/2020\/06\/sec_by_default.jpg 1058w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">As illustrated, the loadinfo for that load would include the following information: A triggeringPrincipal of https:\/\/example.com, because the page https:\/\/example.com actually triggered the load to occur. The loadingPrincipal would also be set to https:\/\/example.com because the result of the JS load will be used in the security context of https:\/\/example.com. The ContentPolicy type will be set to TYPE_SCRIPT which e.g., allows mapping of content type to Content Security Policy directives (in this particular case to the script-src directive). Finally, the security flags would be set to ALLOW_CROSS_ORIGIN because JavaScript files are allowed to be loaded cross origin.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">While in that particular case Firefox would allow the cross origin load, it would still ensure that the web page is not trying to access the local file system of the end user.<\/span><\/p>\n<p>&nbsp;<\/p>\n<h2><span style=\"font-weight: 400;\">Going Forward<\/span><\/h2>\n<p><span style=\"font-weight: 400;\">In this blog post, we explained how Firefox enforces Web Security checks, like the Same-Origin Policy. In the next post we\u2019ll explain how to enable available logging mechanisms which allow for visual inspection of every web security check performed. We hope that this introduction will aid security research as well as bug bounty hunting and sparks your curiosity to go further, even contribute to Mozilla and the Open Web.<\/span><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is the first part of a blog post series that will allow you to understand how Firefox implements Web Security fundamentals, like the Same-Origin Policy. This first post of &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/attack-and-defense\/2020\/06\/10\/understanding-web-security-checks-in-firefox-part-1\/\">Read more<\/a><\/p>\n","protected":false},"author":960,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[449525],"tags":[],"coauthors":[280776,280726],"_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/posts\/143"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/users\/960"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/comments?post=143"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/posts\/143\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/media?parent=143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/categories?post=143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/tags?post=143"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mozilla.org\/attack-and-defense\/wp-json\/wp\/v2\/coauthors?post=143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}