In this post we will discuss why developers should implement integrity checking of scripts and other related resources.
To start, what is integrity checking? Integrity checking involves using a hashing algorithm to create a cryptographic hash of the content of a file.
If this same file gets altered in any way, the hash will be different.
For example, this is the jQuery’s CDN link which includes the integrity attribute using the SHA256 hashing algorithm:
The displayed hash is the hash calculation at the time of release. So, in the event of this file getting changed and the hash not getting updated, this will not get loaded. Not having integrity checking will allow for file changes to happen and these will happily get loaded.
Ultimately, the question here will most likely be how this could ever cause an issue. An example of an issue would be the use of a service provider to store assets. Here are some of the risks:
- Unauthorised change occurring due to an unforeseen reason,
- An insider tampering with the resources
- A hacker with malicious intent.
To expand on this example would be the use of a “Subdomain Takeover”. This occurs when there has been a misconfiguration when using an external service provider to host a site or assets.
To demonstrate this, we have the following:
exdemo1.com -> testsite-demo1.herokuapp.com (Main Site)
test.exdemo1.com -> guarded-waters-47619.herokuapp.com (Serving test.js to main site)
The below screenshot shows the test.exdemo1.com setup:
Hosted on test.exdemo1.com, is test.js. When visiting exdemo1.com, test.js gets loaded from test.exdemo1.com and an alert is executed. This being the correct test.js:
Now, if the host guarded-waters-47619.herokuapp.com which serves test.js is removed without any other further configuration change, what could happen? This may be a problem (see the before and after screenshots below). To continue this, guarded-waters-47619.herokuapp.com will be removed from the main account. However, the DNS CNAME record will be left pointing to guarded-waters-47619.herokuapp.com as previously shown in the above nslookup screenshot.
Attempting to load the main site again will now show an error 404 (Not Found) for test.js:
We go over to a different account, and re-create guarded-waters-47619.herokuapp.com again (as it doesn’t exist anymore) and push a modified test.js to it:
When the main site is now accessed, it will still show an error 404:
There needs to be a custom domain setup to make this work. So, we’ll just create it with this different account that guarded-waters-47619.herokuapp.com was re-created with:
Except for some minor modifications which were required, when we now access the main site again this should load the test.js. However, with the slight change that was made to test.js this will now show a different alert message:
Now it has been shown how a script (test.js in this case) could be modified in this scenario and get executed due to not utilising integrity checking. We will go through how to setup integrity checking. For further information on this you can go to https://www.srihash.org/.
Use the following command to generate a base64 encoding of a SHA256 hash. Please note, this is slightly different to the mentioned command in the URL above:
openssl dgst -sha256 -binary FILENAME.js | openssl base64 -A
Just like the jQuery script snippet, the script tag within the main site has been adjusted to include a SHA256 integrity hash of the original test.js:
When reloading this again the script doesn’t execute and shows a console message that the integrity hash doesn’t match the test.js content which is being received:
As you can see, integrity checking is great for making sure any externally hosted assets are the ones that are intended and not malicious.