Using Subresource Integrity to Secure Externally Hosted Content
One simple trick that can prevent you from distributing malware or aiding a DDoS attack from your CDN.
Many CDNs provide hosting of common JavaScript libraries and CSS frameworks. Everyone loves using them since it’s basically free hosting and free performance. But since you don’t control the CDN or the content it is hosting, it’s possible the content could be compromised and is sending data that harms you or your customers. Sound crazy? It’s happened before.
- The CDN itself it compromised and is sending malicious content. Fortunately I’m not aware of any examples here, but if it happened, it would be a very bad day for the Internet.
- The Origin is compromised and bad data is uploaded to the CDN. A variation of this happened recently with Mint Linux.
- A MITM attack (with or without TLS) that intercepts and alters externally hosted data mid-stream. This is how the Great Cannon was able to cripple GitHub in March 2015.
Subresource integrity is easy to add and
prevents most if not all cases above. You add the appropriate
cryptographic hash to your script
and link
tags that point to your
CDN. If the data downloaded doesn’t match the hash, the data is
discarded. Your site might break, but you also won’t be distributing
malware or unintentionally aiding DDoS attack.
Here’s a sample from getbootstrap.com (This is actually how I found out subresource integrity in the first place).
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7"
crossorigin="anonymous">
The integrity
attribute contains the cryptographic hash and
crossorigin
attribute is for CORS. Much more detail can be found in
the Mozilla Developer
Network.
It’s so simple and so effective, it’s amazing it wasn’t developed
years ago.
It would be fantastic if the CDNs started to publish SHA-384 hashes of the content they are hosting. I suspect in time they will. Until then, there are a number of ways to add subresource integrity hashes:
- Using the online tool srihash
- Manually using
cat FILENAME.js | openssl dgst -sha384 -binary | openssl enc -base64 -A
(accordiing to developer.mozilla.org - Automatically with a number of tools. See the subresource integrity wiki for details.
According to caniuse.com, as of 2016-02-29, somewhere between 40-50% of all web browsers supports subresouce integrity. If you add subresource integrity tags, be sure to test in either the latest Chrome or Firefox browsers. Sadly Safari and IE do not support it yet.
It is good to know if a subresource integrity checks fails. Frederik
Braun
wrote up some tips on how to check and report failures (he’s also one
of the editors of the
specification).
It’s not clear to me if on failure an event
is created or not.
While this is mostly focused on CDNs hosting external content, it’s also valuable if you are using a CDN to host your own content. The authenication mechanisms to deploy to your web site and deploy to a CDN are different. With SRI, you can detect possible compromise. Considering how easy it is to add, and given the severity of the issues it prevents, there is very little reason not to add subresource integrity attributes.