If you’ve read our previous posts on Content Security Policy, you know that we spent a good amount of time getting our site to work using a fairly strict CSP. Something we recently discussed in our presentation at AppSec USA was the fact that most browsers are currently ineffective when it comes to blocking Java Applet execution with CSP. This post will share more details on what we found regarding applet execution and CSP.
Here at SendSafely, we use a Java Applet for backwards compatibility with browsers that don’t support all of the HTML5 APIs our application uses. When we did our initial testing of CSP, one thing we noticed was that no matter what the CSP policy was set to block, our test page was still able to load our Java Applet. We were seeing this behavior across all of the browsers we tested, specifically Chrome, Firefox and Safari (which all have pretty complete CSP 1.0 support). Even with a completely locked-down CSP that had default-src and object-src both set to ‘none’, each of these browsers happily loaded our applet despite refusing to load any other content (no images, no CSS, no JavaScript). Something definitely seemed wrong.
Our first thought was that this was a little too obvious to be a bug since all three browsers behaved the same. We figured we would take another look at the specification to make sure we weren’t missing something obvious. The following extract from the CSP specification (http://www.w3.org/TR/CSP/#object-src) was the part we were most interested in.
The gist of this section of the spec is that the user-agent (the browser) should enforce object-src CSP restrictions on the EMBED, OBJECT and APPLET tags. The following quote summarizes how the browser is supposed to behave:
Whenever the user agent fetches a URI (including when following redirects) in the course of one of the following activities, if the URI does not match the allowed object sources, the user agent must act as if it had received an empty HTTP 400 response
The spec also goes on to include the following as one of the referenced activities:
Requesting data for a plugin, such as when processing the data attribute of an object element, the src attribute of an embed elements, or the code or archive attributes of an applet element.
A closer look at our code revealed that we were using the APPLET tag to launch the applet. This made us a little curious so we decided to experiment by loading the applet using OBJECT and EMBED tags in each of the three browsers. The table below summarizes what we saw.
As shown above, the applet always loads on Firefox regardless of whether we used an APPLET tag or OBJECT/EMBED tags. Chrome and Safari both seem to properly block the applet from loading when OBJECT/EMBED tags are used but do not block the APPLET tag. Although Firefox didn’t block Java using the OBJECT/EMBED tag we did notice that other plug-ins (specifically Flash) do get blocked. This might indicate that Firefox relies on the underlying plugin to enforce CSP restrictions rather than blocking the plug-in from loading, however we do not have sufficient evidence to make a definitive conclusion on that.
We decided that based on the above something seemed wrong, so we decided it was time to start a conversation with people a little more familiar than us on the topic. We started a thread on the W3C webappsec group to see what the CSP expert community had to say. As it turns out, there is still some debate as to how the object-src directive gets enforced, specifically whether the browser or individual plug-ins should enforce CSP restrictions. The case for 1.0 seems fairly clear since you cannot distinguish between content types, but the CSP 1.1 specification includes support for media-types (which may influence the direction that some browsers will take). In any case, there is a general consensus that something like object-src ‘none’ should explicitly stop the browser from attempting to load any plug-ins.
For now it looks like this issue will need to be addressed individually by each browser. As for the CSP we use on SendSafely, we still don’t include any object-src directive (since it is not necessary) but we will likely have to re-visit this as proper object-src blocking gets implemented down the road.