Mixed content issues arise when web sites deliver their pages over HTTPS, but allow some of the resources to be delivered in plaintext. The active network attacker can’t do anything about the encrypted traffic, but messing with the plaintext can result with attacks ranging from phishing in the best case to full browser compromise in the worst. A single exposed script is sufficient: the attacker can hijack the connection and inject arbitrary attack payloads into it.

We tend to talk a lot about other aspects of SSL/TLS, but mixed content is arguably the easiest way to completely mess up your web site encryption.

In the very early days of the Web, all mixed content was allowed; web browsers expected site operators to think through the consequences of mixing content. That, of course, did not result with great security. Site operators did whatever they needed to get their work done and decrease costs. Only in recent years did browser vendors start to pay attention and start to restrict mixed content.

Mixed content in modern browsers

Today, almost all major browsers tend to break mixed content into two categories: passive for images, videos, and sound; and activefor more dangerous resources, such as scripts. They tend to allow passive mixed content by default, but reject active content. This is clearly a compromise between breaking the Web and reasonable security.

Internet Explorer has been the leader in secure mixed content handling. As early as Internet Explorer 5 (according to this post), they had detection and prevention of insecure content by default. Chrome started blocking by default in 2011, and Firefox in 2013. The default Android browser and Safari, however, still allow all mixed content without any restrictions (and with almost non-existent warnings).

Here are the results of my recent testing of what insecure content is allowed by default:

Browser Images CSS Scripts XHR WebSockets Frames Android browser 4.4.x Yes Yes Yes Yes Yes Yes Chrome 33 Yes No No Yes Yes No Firefox 28 Yes No No No No No Internet Explorer 11 Yes No No No No No Safari 7 Yes Yes Yes Yes Yes Yes

They are mostly as expecting, but there’s a surprise with Chrome, which blocks active page content, but still allows plaintext XMLHttpRequest and WebSocket connections.

It’s worth mentioning that the table does not tell us everything. For example, browsers tend not to control what their plugins do. Further, certain components (e.g., Flash or Java) are full environments in their own right, and there’s little browsers can do to enforce security.

Testing for mixed content handling in SSL Labs

To make it easier to evaluate browser handling of this problem, I recently extended the SSL Labs Client Test to probe mixed content handling. When you visit the page, your user browser is tested, and you will get results similar to these:

Mixed content prevalence

Anecdotally, mixed content is very common. At Qualys, we investigated this problem in 2011, along with several other application-level issues that result with full breakage of encryption in web applications. We analysed the homepages of about 250,000 secure web sites from the Alexa top 1 million list, and determined that 22.41% of them used insecure content. If images are excluded, the number falls to 18.71%.

A more detailed study of 18,526 sites extracted from Alexa top 100,000 took place in 2013: A Dangerous Mix: Large-scale analysis of mixed-content websites (Chen et al.). For each site, up to 200 secure pages were analysed, arriving at a total of 481,656 pages. Their results indicate that up to 43% of web sites have mixed content issues.

Mitigation

The best defence against mixed content issues is simply not having this type of problem in your code. But that’s easily said than done; there are many ways in which mixed content can creep up. When that fails, there are two technologies that can come useful:

HTTP Strict Transport Security (HSTS) is a mechanism that enforces secure resource retrieval, even in the face of user mistakes (attempting to access your web site on port 80) and implementation errors (your developers place an insecure link into a secure page). HSTS is one of the best thing that happened to TLS recently, but it works only on the hostnames you control.

is a mechanism that enforces secure resource retrieval, even in the face of user mistakes (attempting to access your web site on port 80) and implementation errors (your developers place an insecure link into a secure page). HSTS is one of the best thing that happened to TLS recently, but it works only on the hostnames you control. Content Security Policy (CSP) can be used to block insecure resource retrieval from third-party web sites. It also has many other useful features for to address other application security issues, for example XSS.