For the last few months, I’ve been working on the Mixed Content Blocker for Firefox. I’ve been landing patches since Firefox 18 in hope of reaching this day. Mixed Active Content is now blocked by default in Firefox 23!
What is Mixed Content?
When a user visits a page served over HTTP, their connection is open for eavesdropping and man-in-the-middle (MITM) attacks. When a user visits a page served over HTTPS, their connection with the web server is authenticated and encrypted with SSL and hence safeguarded from eavesdroppers and MITM attacks.
However, if an HTTPS page includes HTTP content, the HTTP portion can be read or modified by attackers, even though the main page is served over HTTPS. When an HTTPS page has HTTP content, we call that content “mixed”. The webpage that the user is visiting is only partially encrypted, since some of the content is retrieved unencrypted over HTTP. The Mixed Content Blocker blocks certain HTTP requests on HTTPS pages.
What do I mean by “certain HTTP requests”? Why wouldn’t the Mixed Content Blocker just block all HTTP requests? To answer this question, I will first explain how the browser security community divides mixed content into two categories; Mixed Active Content and Mixed Passive Content.
Mixed Passive Content (a.k.a. Mixed Display Content).
Mixed Passive Content is HTTP Content on an HTTPS website that cannot alter the Document Object Model (DOM) of the webpage. More simply stated, the HTTP content has a limited effect on the HTTPS website. For example, an attacker could replace an image served over HTTP with an inappropriate image or a misleading message to the user. However, the attacker would not have the ability to affect the rest of the webpage, only the section of the page where the image is loaded.
An attacker could infer information about the user’s browsing activities by watching which images are served to the user. Since certain images may only appear on a specific webpage, a request for an image could tell the attacker what webpage the user is visiting. Moreover, the attacker can observe the HTTP headers sent with the image, including the user agent string and any cookies associated with the domain the image is served from. If the image is served from the same domain as the main webpage, then the protection HTTPS provides to the user’s account becomes useless, since an attacker can read the user’s cookies from image request headers[1].
Examples of Passive Content are images, audio, and video loads. Requests made by objects have also fallen into this category for now; the reasons for this are discussed further in the Appendix.
Mixed Active Content (a.k.a. Mixed Script Content)
Mixed Active Content is content that has access to and can affect all or parts of the Document Object Model (DOM) of an HTTPS page. This type of mixed content can alter the behavior of an HTTPS page and potentially steal sensitive data from the user. Hence, in addition to the risks already described for Mixed Passive Content above, Mixed Active Content is also exposesd to a number of additional attack vectors.
A MITM attacker can intercept requests for HTTP active content. The attacker can then re-write the response to include malicious JavaScript code. Malicious script can steal the user’s credentials, acquire sensitive data about the user, or attempt to install malware on the user’s system (by leveraging vulnerable plugins the user has installed, for example).
Examples of Active Content are JavaScript, CSS, objects, xhr requests, iframes, and fonts.
The Mixed Content Blocker will block Mixed Active Content requests in Firefox 23. This reduces the threat to the user, but does not eliminate it completely because Mixed Passive Content is still permitted. Users can decide to block Mixed Passive Content as well by following a couple simple steps[2].
Why are we reducing the threat instead of eliminating the threat? Unfortunately, the web is not ready for Firefox to block Mixed Passive Content. Mixed Passive Content is still common on the web. For example, many HTTPS webpages include HTTP images. Too many pages would break if we blocked Mixed Passive Content (ex: https://youtube.com). Hence, Firefox would alert users too often and contribute to security warning fatigue.
Moreover, blocking Mixed Passive Content could cause considerable user experience issues for users with low bandwidth connections. To avoid generating a browser security warning, websites will begin removing Mixed Passive Content from their HTTPS sites by replacing HTTP images and videos with their HTTPS equivalent versions. When low bandwidth users visit the HTTPS site, all image loads and video streams would be encrypted and there would be considerable lag in the page’s load time and the time it takes for videos to buffer. With Mixed Active Content, bandwidth considerations are not as big of an issue since Mixed Active Content loads (ex: scripts, stylesheets) are usually a few KB, compared to Mixed Passive Content loads which often contain multiple MBs of data.
The risk involved with Mixed Content (active or passive) also depends on the type of website the user is visiting and how sensitive the data exposed to that site may be. The webpage may have public data visible to the world, or it may have private data that is only visible when authenticated. If an HTTP webpage is public and doesn’t have any sensitive data, the use of Mixed Content on that site still provides the attacker with the opportunity to redirect requests to other HTTP URLs and steal HTTP cookies from those sites.
I don’t have Firefox 23 yet. Can I enable the Mixed Content Blocker?
Work on the Mixed Content Blocker first landed in Firefox 18 and has been incrementally improving since.
The Mixed Content Blocker UI does not exist in Firefox 18, 19, and 20. You can turn the feature on BUT if you encounter a page that breaks because a mixed content resource is blocked, the only way to fix the page and load the insecure content is to turn the feature off. This makes the feature difficult to use in FF 18, 19 and 20.
Firefox 21 and 22 (currently Firefox Beta and Aurora, respectively) shipped with the Mixed Content Blocking UI. You can turn on the feature and try it out[3]! (Note that there is a case that is incorrectly blocked in Firefox 21 that was fixed in Firefox 22 with Bug 841850).
Mixed Content Blocker UI
Designing UI for security is always tricky. How do you inform the user about a potential security threat without annoying them and interrupting their task?
Larissa Co (@lyco1) from Mozilla’s User Experience team aimed to solve this problem. She created a Security UX Framework with a set of core principles that drove the UX design for the Mixed Content Blocker. If you’re interested in learning more about this process, I encourage you to check out the Mixed Content Design Specification and Larissa’s presentation on Designing Meaningful and Usable Security Experiences.
So what does the UI look like? If a user visits an HTTPS page with Mixed Active Content, they will see the following in the location bar:
Clicking on the shield, they will see options to Learn More, Keep Blocking, or Disable Protection on This Page:
If a user decides to “Keep Blocking”, the notification in the location bar will disappear:
On the other hand, if a user decides to “Disable Protection on This Page”, all mixed content will load on the HTTPS page and the Lock icon will be replaced with a Yellow Warning Triangle:
If the user is unsure what to do, they can opt to learn more by clicking on the “Learn More” link. The user can also select “Not Now” or the “x” at the top of the drop down box to defer their decision until later.
If a user visits an HTTPS page with Mixed Passive Content, Firefox will not block the passive content by default (see What will the Mixed Content Blocker block?). But, since Mixed Passive Content does exist on the page, it is not fully encrypted and the user will not see the lock icon in the location bar:
Note that frames are classified as Mixed Active Content. This has been a source of debate and browser vendors haven’t quite settled on whether mixed content frames should be considered active or passive. Firefox and Internet Explorer consider frames Mixed Active Content, while Chrome considers frames Mixed Passive Content.
When trying to determine whether a load is passive or active, I ask myself “can the content affect the DOM of the page?”. With frames, this gets a little tricky. Technically, an HTTP frame cannot affect the DOM of its HTTPS page and hence could fall into the Mixed Passive Content category.
When we dig further, however, we find reasons to push frames into the Mixed Active Content category. A frame has the ability to navigate the top level page and redirect a user to a malicious site. Frames can also trick users into disclosing sensitive information to attackers. For example, assume a user is on an HTTPS page that embeds an HTTP frame. An attacker can MITM the frame and replace its content with a form. The form may ask the user to login or create an account. Most users are oblivious to the concept of framing pages and have no idea that it is the HTTP frame that contains the form and not the HTTPS website. Assuming they are on the HTTPS encrypted page, the user enters their personal information. This information is then sent to the attacker without the user’s knowledge.
Remaining Edge Case
Many edge cases were found while developing the Mixed Content Blocker. Some of these edge cases have been resolved, some are pending development, and some are open questions that require further discussion.
We did not want to wait until all possible issues were resolved before turning Mixed Active Content blocking on by default for our users. But at the same time, if we turned the feature on with too many false positives, we would be unnecessarily alerting users and contributing to security warning fatigue. (False positives are cases where the Mixed Content Blocker mistakenly blocks content that should have been permitted.) Hence, I worked to eliminate all false positive issues that I was aware of before turning on the Mixed Content Blocker.
On the other hand, there are still a number of false negatives that remain open. This means that there are certain cases where the Mixed Content Blocker does not block content that should have been blocked. We still decided to turn the feature on because we believe we should protect our users as soon as possible, even if our solution is not 100% perfect yet. The false negatives are valid issues and affect the safety of our users. Engineering solutions for these edge cases is important (and is next on my list), but should not prevent us from protecting users from mixed content we can identify and can block for users today.
For developers trying to secure their websites by removing mixed content, these false negative edge cases could prove problematic and cause extra work. The last thing a developer wants to do is attempt to remove mixed content on their site for Firefox 23, and then have to do this again in Firefox 24 because of an edge case that was fixed and that the developer wasn’t aware of the first time around. In an attempt to help with this problem, I have an added an Appendix to this blog post that will describe all the open edge cases and open questions with reference links where developers can learn more about the progress in resolving these known issues.
Thank You
Thanks to all the Mozillians that have helped me with this feature. Special shouts out to…
Olli Pettay (smaug)
Brandon Sterne (@bsterne)
Larissa Co (@lyco1)
Ian Melven (@imelven)
Sid Stamm
Brian Smith
Justin Dolske (@dolske)
Gavin Sharp (@gavinsharp)
Matthew Noorenberghe
Couldn’t have done it without you 🙂
Footnotes
[1] Unless the authentication cookies are flagged with the secure bit, preventing the browser from sending the authentication cookies for non-HTTPS requests.
[2] To block Mixed Passive Content, open a window or tab in Firefox and enter about:config. You will get to a page that asks you to promise to be careful. Promise you will be, and then change the value of security.mixed_content.block_display_content to true by double clicking it.
[3] In Firefox 23+, Mixed Active Content is blocked by default. If you are using a Firefox version between 18 and 22, you can block Mixed Active Content by opening a window or tab in Firefox and enter about:config. You will get to a page that asks you to promise to be careful. Promise you will be, and then change the value of security.mixed_content.block_active_content to true by double clicking it.
Note that this section is highly technical and has a lot of gory details, so feel free to skip over it unless you are interested, want a sneak peak at forthcoming Mixed Content Blocker changes that may affect your site, and/or are a browser security junkie like me 🙂
- Redirects
If an HTTPS content load responds with a 302 to an HTTP destination, the Mixed Content Blocker in Firefox will not detect or block the mixed content. This is because of the way that Gecko’s Content Policies work (or don’t work) with redirects. The work to fix this edge case can be found in Bug 418354 and Bug 456957.
- Session Restore & document.write
Assume an HTTPS page loads an HTTP script that invokes a document.write that replaces the current page’s content. If the browser is shut down and later the session is restored, the user will see the content from the document.write that replaced the original webpage. This would be okay, except that instead of showing the yellow warning triangle, Firefox 23 shows a lock. This is inaccurate, because the page’s new content was created by an HTTP script and hence cannot be considered fully encrypted. The work to fix this issue can be found in Bug 815345.
- Object Subrequests
Assume that an HTTPS page loads an HTTPS object in a plugin. That object may then request further resources through the plugin. The requests made by the plugin are considered the object’s subrequests. Since the requests are made by a plugin and not by the browser, it is very difficult for the browser to determine whether the HTTP subrequests should be considered Mixed Active or Mixed Passive. Without help from plugin vendors, browsers cannot accurately determine this classification. To prevent false positives and security warning fatigue, Firefox (and Chrome) have classified HTTP object subrequests as Mixed Passive Content. This means that we do have false negatives, where the content is actually active and should be blocked, but isn’t.
The solution to these false negatives is still under discussion. Take a look at Bug 836352 and chime in if you have some suggestions!
- Relying on HSTS to prevent Mixed Content
Websites can specify an HSTS header that tells browsers to only connect to them over a secure connection. Assume https://example.com sets this header (and for simplicity sake, assume example.com is not on the HSTS preload list). A developer, relying on HSTS, includes HTTP content from example.com on https://foo.com.
Firefox will convert the http://example.com link to an https://example.com link before making the network request. Hence, technically, the user’s security is never affected.
Currently, the Mixed Content Blocker will detect the http://example.com link before it is converted to HTTPS by HSTS and classify the content as mixed content. I believe this is fine. Relying on HSTS to protect websites from mixed content loads is bad practice, for the following reasons.
- If this is the first time the user has loaded content from example.com, the content will be loaded over HTTP since the browser has not yet received and HSTS header from example.com
- For browsers that do not have HSTS implemented (ex: Internet Explorer), https://foo.com will have mixed content, since the request for content from http://example.com is never converted to an HTTPS request.
Perhaps you disagree? Express your thoughts in Bug 838395
- Mixed Content in Framed Pages
Assume https://unimportant-site.com includes an iframe to https://bank.com. https://bank.com contains Mixed Active Content that Firefox blocks. The user has a choice to “Disable Protection on This Page” and load the Mixed Active Content on https://bank.com. As we mentioned earlier, most users don’t know what frames are. The user see’s that they are on https://unimportant-site.com and can decide to load the mixed content on https://unimportant-site.com by clicking “Disable Protection on This Page”. To the user, “This Page” is https://unimportant-site.com, but in actuality, the result is that protection is disabled on https://bank.com.
Bug 826599 discusses whether users should even have an option to disable protection on HTTPS frames. The bug is to remove the UI to Disable Protection if the mixed content is coming from an HTTPS frame with a different domain than the top level domain. What do you think about this?
In addition to the items listed above, there are also many other issues remaining to improve the Mixed Content Blocker. You can see here for a list of items and corresponding bug numbers.