Web technologies like TLS, HSTS and pinned public keys make sure that webpage resources are downloaded from the correct host. But these methods fail to verify if the downloaded resource is manipulated or not. For example, a attacker having access to the resource server can manipulate the resource(make it vulnerable to the app) and this kinds of attacks cannot be protected by using TLS or other similar technologies. Below image shows exactly how this attack is done.
Till now administrators prevented this kinds of attacks by automatic checks for file and directory changes. If there is a change(attack) then admin used to restore the server to prevent the attacks. But there was no browser side method for stopping this attacks.
But now subresource integrity can protect from these kinds of attacks. Its a way of matching resources hash values with the hash value provided in the webpage. Ofcourse a attacker who can manipulate the resource can also manipulate the hash value in webpage therefore subresource integrity should only be used when the webpage host is different then the resources host i.e., while downloading third party resources like jQuery, Google maps scripts etc.
Subresource Integrity in Nutshell
Subresource integrity is achieved by attaching integrity attribute to HTML elements which downloads external resources(link, img, script, track, iframe, video, audio, a etc). This attribute to a value which is combination of resource hash value, hashing algorithm and MIME type of the file.
integrity="ni:///sha-256;C6CB9UYIS9UJeqinPHWTHVqh_E1uhG5Twh-Y5qFQmYg?ct=application/javascript">
“ni” in the integrity attribute stands for “named information”.
Here browser first downloads the script file and then matches the MIME type in HTTP header and hash of the returned code. If both are matched then the javascript code is executed otherwise ignored. If the file is a non-browser executable file(ex: .exe) then browser downloads it and if hash doesn’t match then it deletes the file.
Generating Hash of a file
Hash of a file(text or binary) can be generated using OpenSSL utility.
Make sure that the final hash is base64 encoded and choose sha256 or sha512 as hashing algorithm because all browsers support these two algorithms.
Fallback support
If the hash value of the resource is not matched then we might want the browser to download the resource from somewhere else. In that case we can provide the noncanonical-src attribute to provide the original resource location and if verification fails then resource attached to src(or main resource attribute) attribute is downloaded.
integrity="ni:///sha-256;C6CB9UYIS9UJeqinPHWTHVqh_E1uhG5Twh-Y5qFQmYg?ct=application/javascript">
This is mainly done for performance issue(HTTP is faster then HTTPS) and also for caching issues(some resource server forget to return caching headers). The non-canonical attribute usually points a resource location which is faster(HTTP) and also returns proper caching headers. If this location is hacked then browser fallbacks to an another location specified.
Integrity checks for <a> tag
Integrity(hash validation) checks can only be done on the anchor elements if there is a download attribute on the anchor element. So browsers completely downloads the resource and verifies its hash, if not matched then deletes the downloaded file.
If download attribute is not specified but integrity attribute is specified then user will not open the link. Its the only type of download support on the anchor elements.
Integrity check for resources fetched using JavaScript
Web workers, AJAX, HTMLElement objects, etc fetch external resources. We can also check their integrity.
For web workers we can pass the integrity attribute value to the constructor(new Worker) second parameter.
While creating HTML elements using JavaScript we can set the integrity attribute using setAttribute function.
XMLHttpRequest objects exposes a attribute called as integrity to which we can assign the ni string.
Conclusion
Subresource integrity is only supported by the latest browsers. Its will under heavy development. But you can start using it write away as non-supporting browsers will cause no harm. Thanks for reading.