Tuesday, June 23, 2015

Subresource Integrity is coming to the modern browsers near you

Great news - just a couple of months ago (on the 5th of May) W3C has delivered a working draft for Subresource Integrity (SRI) specification. From the abstract:

This specification defines a mechanism by which user agents may verify that a fetched resource has been delivered without unexpected manipulation.
Why am I exciting about this announcement? Well, the key phrase here is "verify that ... delivered without manipulation". This feature alone is not a panacea for all the bad stuff happening on the Internet. But it is an excellent defence in depth measure that (in many cases) doesn't cost too much time and effort to implement.

Many web sites embed resources like css or javascript. Sometimes those resources are hosted on the 3rd party web sites. E.g. you may find it easier to reference a boostrap CSS file from http://www.bootstrapcdn.com/ or the latest version of jQuery from http://code.jquery.com/jquery-git2.min.js. But what if one of the sites hosting those resources gets compromised? The security of your web site will be affected.

We have also seen cases of content delivered across the wire being modified on the way to the end users (e.g. ISPs or WiFi hotspot operators injecting ads or governments stealing credentials). By supporting SSL/TLS and loading websites via HTTPS we can protect the content of the web pages. SRI helps to further improve security by allowing a server to supply an additional piece of information to the client (browser) to ensure that this particular resource hasn't been modified/tampered with.

This additional piece of information is officially called "integrity metadata". This is just a base64-encoded hash of the resource. The specification says that servers/clients MUST support SHA-2 hashes (i.e. SHA-256, SHA-384, SHA-512) and MAY support other cryptographic functions. By supplying a hash we can (almost - aside from a hash collision scenario) guarantee that the resource hasn't been modified from the moment when the hash has been generated.

Note: if an attacker controls the web server then he/she can produce valid hashes.

Now putting it all together - this is how it will most likely look like:

<script src="https://analytics-r-us.com/v1.0/include.js"

Here we can see a standard script tag that embeds an external include.js javascript file and a newly introduced "integrity" attribute, that specifies a SHA-256 hash of the include.js file. A client side (browser) now has the ability to download this resource, recalculate the hash and compare the result with the value supplied in the integrity attribute. If 2 values don't match then this resource needs to be discarded (it can't be trusted).

It will also be possible to specify multiple hash values for the same resource

<script src="hello_world.js"

In this scenario client will be able to choose the strongest supported hash function.

Note: some examples that you might find on the Internet use an older syntax (notice the "ni" part that stands for "named information" as defined in RFC6920):


Around January 2015 the specification has been updated to adopt the same format as CSP Level 2 for the hash format. So the "ni" part is no longer required.

In addition to link (css) and script tags the future versions of SRI will support other types of resources - e.g. file downloads referenced in A tags or even iframes.

From the information I have, it looks like SRI will be fully supported in Firefox v.42.
It is currently "under consideration" for Microsoft Edge. Most likely it won't be implemented in IE11.

In conclusion I would like to share 2 links with you:

SRI hash generator - will make it easier to calculate hashes

W3C SRI test - will run the test and show how well SRI is supported in your browser of choice.