Subresource Integrity or SRI, is a web browser security feature that verifies the integrity of resources loaded into an HTML page.
A web developer declares an expected cryptographic hash value for the target resource in the
<link> tag and, browsers implementing SRI will compute the checksum when the resource is loaded and refuse to load it if it does not match the developer’s expected value.
SRI gives us a way to get back some control over this by establishing a point in time where the resource is “trusted” and only allowing this version to load.
As an example, this very page, at the time of writing uses jQuery (I know, old skool right?!) and we load it from a CDN. If you have a look at the source HTML you will see the script tag which does this has an additional integrity attribute.
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
If you want to know more about SRI I’d recommend the Mozilla Developer article at https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity.
Checking for SRI
When we’re conducting web application penetration testing engagements, one of the checks we perform is for the use of remote resources without the use of SRI. We use the excellent OWASP Application Security Verification Standard as the basis for most of our app testing and SRI is control requirement 14.2.3.
The majority of the time it’s easy for us to identify this using passive scanning in Burp Suite Professional. As we work through the site it will automatically populate resources without SRI which makes our job a lot easier. However, the majority of our clients don’t have Burp Suite but do need a way to list out affected resources on their site as part of any remediation work they may wish to conduct to address this.
For this purpose I put together a really simple Python script that can be used to check all the resources on a supplied URL and flag up any that do not have SRI. We’ve found it’s been quite useful for a number of clients so I decided to open source it.
You can find the tool at https://github.com/4armed/sri-check along with instructions on how to get it up and running. It only has a couple of external dependencies,
Once installed you can just give it a target URL and it’ll do its thing. For example, you could check our Content Security Policy test page (The eagle-eyed *nix people will spot that I have it in my
PATH, you may not):
$ sri-check https://csp.4armed.io/csptest.html
Naughty 4ARMED. There’s no SRI on that jQuery resource. It’s also got a known vulnerability but that’s a separate item to deal with! Sometimes it’s useful to know if there are other resources on the page which do have SRI. For that we can use the
-a flag to print all resources instead.
$ sri-check -a https://csp.4armed.io/csptest.html
<script crossorigin="anonymous" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script
Ok, so we weren’t completely irresponsible, the Bootstrap resource has SRI.
Generating SRI hashes
So we know we’ve got a problem but how do we fix it? The Mozilla article gives some examples of how you can use
openssl to generate a hash, or there’s a great website at https://srihash.org where you can enter the URL of the resource and it will generate an SRI enabled tag for you.
However, seeing as we’ve got this tool, I figured it made more sense to just bake it right in here. If we use the
-g or long form
--generate flag sri-check will create the tags for us.
$ sri-check -g https://csp.4armed.io/csptest.html
[*] Resource tags without SRI:
[*] Generated SRIs:
<script crossorigin="anonymous" integrity="sha384-nvAa0+6Qg9clwYCGGPpDQLVpLNn0fRaROjHqs13t4Ggj3Ez50XnGQqc/r8MhnRDZ" src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
This really is a super simple tool. There was barely an hour of coding to put it together so I’m sure there’s ways to improve it. A crawler would be quite nice so you can do an entire site perhaps. Although, generally in our experience, most assets are defined in shared templates and it’s unusual for a site to have lots of different resources in lots of different places. It does happen though. Often where a site is currently being migrated from an old frontend to a new one.
Maybe you’ll find it useful. Maybe as a developer, or maybe as a security tester who needs to show their clients where they don’t have SRI.
If it helps you out it would be great to know. If you’ve got any questions or you’d like us to have a look at more than just your SRI, you can get in touch and we’d be happy to help out.