Staff Security Engineer
Mozilla Corporation
When most people think about website security,
they think about this:
What about your seasoned security professional?
A+ on SSL Labs? Time to call it a day!
Who here has seen code like this?
<script src="https://code.jquery.com/jquery-3.1.1.min.js">
I'll get into that shortly, but first you must understand...
Sites can retrieve and execute code from any origin, but not read its contents.
https:// www.mozilla.org :443
And once that piece of code is executing, it can read the contents of the same-origin, that is, the scheme, hostname, and port number match.
<script src="https://code.jquery.com/jquery-3.1.1.min.js">
When you execute this code, you allow it to:
It could simply deface your fine website.
Or it could do something like @kkotowicz's XSS-Track...
... and create a full-page iframe of your site's login page, easily stealing a user's credentials upon entry.
After all, you're obviously not loading code from Eve & Mallory's Discount JavaScript Emporium!
This is jQuery!
It's the #1 most trusted name in, err… jQuery-ing.
And it's not just a jQuery problem…
If it's such a problem, why does anyone use this?
<script src="https://code.jquery.com/jquery-3.1.1.min.js">
All of the A+ scores in the world won't help you if you load a script from a compromised source
SRI is a W3C standard that protects from remote resources being tampered with.
First, generate a message digest (hash) of the known-good file in question:
Because of how cryptographic hash functions work, only this exact file could produce this would produce this hash. Even the slightest modification would result in a completely different hash.
Then, simply update your tags like so:
<script src="https://code.jquery.com/jquery-3.1.1.min.js"
integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw="
crossorigin="anonymous">
Note: SRI also works with <link> tags!
So easy, it's practically magic!
integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw="
The integrity attribute tells the browser to not load the resource if it doesn't match the correct hash.
crossorigin="anonymous"
And the crossorigin attribute tells your browser to access the resource anonymously, that is, without cookies.
SRI supports the use of multiple hash functions:
integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=
sha384-R4/ztc4ZlRqWjqIuvf6RX5yb/v90qNGx6fS48N0tRxiGkqv…
sha512-Pcrh/26Yxk41hr4+sU3UhsUffU6fobj5pii+T7tqmrVi8x+bUOF…"
SRI also supports multiple valid hashes
for the same hash function:
integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=
sha256-WcPSxGS3bNGjGRf+IUacL3pV4FDKghcLrO3Mz0pirl4=
sha256-hfc4X3ktNhCJuFB8dnhZXAN155eQmiEesLLyuuI2/YQ="
<script>
window.jQuery || (function() {
var lib = document.createElement('script');
lib.src = '/assets/js/jquery-3.1.1.min.js';
document.head.appendChild(lib);
})();
</script>
Simply detect to see if the library has loaded. If it hasn't, then load a locally hosted version.
You can also bind to the tag's onError() event handler.
Content Security Policy (CSP) is a header that servers can send that defines what sources your browser is allowed to load.
The require-sri-for directive can force browsers to require SRI for any scripts and/or styles that a page loads.
Content-Security-Policy: require-sri-for script style
Didn't you say earlier that you can execute code on foreign origins, but not read it? So how can you compute the hash if you can't read the content?
Drats! I would have gotten away with it, if it wasn't for you meddling security professionals!
Imagine a wifi router on a foreign origin
that returns the following page to a logged-in user:
{ "user": "admin", "password": "pass1234" }
In such a case, an XSS attack could calculate the hashes for thousands of passwords, set the integrity attribute, and keep trying to load the resource until it succeeded.
Luckily for us, there's a solution to this conundrum/quagmire/disaster/apocalypse.
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin (ACAO) is part of the cross-origin resource sharing (CORS) standard.
Servers can set this header, opting in to allow foreign origins to read the contents of their pages.
CDNs host public content, so there is no risk in allowing foreign origins to read their contents.
If the server doesn't set the ACAO header,
the integrity check will automatically fail.
🎉 Good news: most CDNs are already setting this header! 🎉
Is SRI intended for HTTP or HTTPS sites?
Origin | Resource | Notes |
---|---|---|
HTTP | HTTP | Prevents MitM/CDN on foreign request |
HTTP | HTTPS | Prevents MitM/CDN on foreign request |
HTTPS | HTTP | Blocked due to mixed content |
HTTPS | HTTPS | Yes! 😍 |
as of November 2016
SRIHash.org can take any URL and generate the proper script tags for you!