Bootstrapcdn recently changed their links. It now looks like this:
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha256-MfvZlkHCEqatNoGiOXveE8FIwMzZg4W85qfrfIFBfYc= sha512-dTfge/zgoMYpP7QbHy4gWMEGsbsdZeCXz7irItjcC3sPUFtf0kuFbDz/ixG7ArTxmDjLXDmezHubeNikyKGVyQ=="
crossorigin="anonymous">
What do the integrity and crossorigin attributes mean? How do they affect the loading of the stylesheet?
Both attributes have been added to Bootstrap CDN to implement Subresource Integrity.
Subresource Integrity defines a mechanism by which user agents may verify that a fetched resource has been delivered without unexpected manipulation Reference
Integrity attribute is to allow the browser to check the file source to ensure that the code is never loaded if the source has been manipulated.
Crossorigin attribute is present when a request is loaded using 'CORS' which is now a requirement of SRI checking when not loaded from the 'same-origin'.
More info on crossorigin
More detail on Bootstrap CDNs implementation
integrity - defines the hash value of a resource (like a checksum) that has to be matched to make the browser execute it. The hash ensures that the file was unmodified and contains expected data. This way browser will not load different (e.g. malicious) resources. Imagine a situation in which your JavaScript files were hacked on the CDN, and there was no way of knowing it. The integrity attribute prevents loading content that does not match.
Invalid SRI will be blocked (Chrome developer-tools), regardless of cross-origin. Below NON-CORS case when integrity attribute does not match:
Integrity can be calculated using: https://www.srihash.org/
Or typing into console (link):
openssl dgst -sha384 -binary FILENAME.js | openssl base64 -A
crossorigin - defines options used when the resource is loaded from a server on a different origin. (See CORS (Cross-Origin Resource Sharing) here: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). It effectively changes HTTP requests sent by the browser. If the “crossorigin” attribute is added - it will result in adding origin: <ORIGIN> key-value pair into HTTP request as shown below.
crossorigin can be set to either “anonymous” or “use-credentials”. Both will result in adding origin: into the request. The latter however will ensure that credentials are checked. No crossorigin attribute in the tag will result in sending a request without origin: key-value pair.
Here is a case when requesting “use-credentials” from CDN:
<script
src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"
integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn"
crossorigin="use-credentials"></script>
A browser can cancel the request if crossorigin incorrectly set.
Links
https://www.w3.org/TR/cors/
https://www.rfc-editor.org/rfc/rfc6454
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link
Blogs
https://frederik-braun.com/using-subresource-integrity.html
https://web-security.guru/en/web-security/subresource-integrity
Technically, the Integrity attribute helps with just that - it enables the proper verification of the data source. That is, it merely allows the browser to verify the numbers in the right source file with the amounts requested by the source file located on the CDN server.
Going a bit deeper, in case of the established encrypted hash value of this source and its checked compliance with a predefined value in the browser - the code executes, and the user request is successfully processed.
Crossorigin attribute helps developers optimize the rates of CDN performance, at the same time, protecting the website code from malicious scripts.
In particular, Crossorigin downloads the program code of the site in anonymous mode, without downloading cookies or performing the authentication procedure. This way, it prevents the leak of user data when you first load the site on a specific CDN server, which network fraudsters can easily replace addresses.
Source: https://yon.fun/what-is-link-integrity-and-crossorigin/
Related
I added a preload for my site like this <link rel=preload href=http://api.github.com/... as=fetch crossorigin=anonymous> which is fetch()ed later. It worked very well (the preload request sent to the remote server at the very beginning of loading, and answer came back, everything was fine).
Later I added an Authorization: Bearer ... to the fetch() call (because of other reasons), which is caused that the preload's HTTP headers do not match the later fetch's HTTP headers, so the entire preload result is not re-used anymore (Both Chrome and Firefox are correctly notify me about this).
I also tried to add the preload with Link HTTP header to the main page's response, but that did not help as well.
So the current sitation is this: I can't add the same Authorization header to preload request because it is simply not possible, so the two request are never will be the same, so the preload is useless anymore.
Please correct me and advise:
Is there a way to add that Authorization: Bearer ... to the preload request to?
OR is there a way to ask the browser to ignore that difference between to two request's headers?
OR any other idea?
Web standards do not allow for such a possibility.
The Fetch standard defines the conditions under which prefetched resources may be used as follows:
To fetch, given a request request, […] run the steps below. […]
If all of the following conditions are true:
[…]
request’s unsafe-request flag is not set or request’s header list is empty
then:
Let foundPreloadedResource be the result of invoking consume a preloaded resource for [request]
Having an Authorization header in the fetch request disqualifies it from reusing preloaded resources. Unless you happen to know of a non-standard extension that allows you to bypass this, this means there is no way to prefetch a resource with custom headers.
There are three ways you can resolve this: skip the Authorization header in the request proper, give up on preloading entirely, or reimplement prefetching yourself. That is, inject a script that fetches the resource early during page loading, preferably gated by network.connection && !network.connection.saveData, and stores it in your own cache, then simply look up the data there.
The order I listed those solutions is one of, in my opinion, decreasing appropriateness. Prefetching has been designed mostly for the sake of static resources that present the same to any user that may want to download them; as such, an Authorization header is not supposed to matter, so if you can get away with avoiding it, do. If authorization does matter, then maybe the resource isn’t such a great candidate for prefetching. If you insist though, you can do it manually.
Currently, for our web application, we are generating nonce values to attach to script tags. I have recently found out about Subresource Integrity and considering that we're using a CDN (as most examples reference), I was curious if this was something my web app should use.
Is there ever a case for both nonce and integrity attributes to be used? Is one better than the other? Or, do they support multiple use cases entirely?
Thanks
They support different use cases and you can use both.
Nonce instructs the browser to execute only <script> elements which have the same nonce value set in the CSP header.
nonce-*
A cryptographic nonce (only used once) to whitelist scripts. The server must generate a unique nonce value each time it transmits a
policy. It is critical to provide a nonce that cannot be guessed as
bypassing a resource's policy is otherwise trivial. This is used in
conjunction with the script tag nonce attribute. e.g.
nonce-DhcnhD3khTMePgXwdayK9BsMqXjhguVV
So let's say your application set a Content-Security-Policy header like script-src'nonce-r4nd0m'; then the script at good.com/good.js will be executed because the nonce value is the same.
<script nonce="r4nd0m" src="//good.com/good.js">
What happens if an attacker compromises good.com and add a malicious script to good.js? That your web application still allows the execution of that script because the check is made on the nonce value not on the script content. So you need also to be sure that the content of good.js remains the same.
Here integrity attribute is involved. It implements Subresource Integrity and tells to the browser to run resources only if the computed hash matches with the one stored in the integrity attribute.
Subresource Integrity (SRI) is a security feature that enables
browsers to verify that resources they fetch (for example, from a CDN)
are delivered without unexpected manipulation. It works by allowing
you to provide a cryptographic hash that a fetched resource must
match.
So let's suppose the first time you included the script in the web app, the content of the script was safe and the integrity value was X. Then you added integrity="sha384-X" to the script element as follows.
<script src="//good.com/good.js"
integrity="sha384-X">
The attacker modifies good.js so the resulting hash of the modified script becomes Y. The browser doesn't run the script because the computed hash (Y) and the required hash (X) don't match.
I think you can combine both like this.
<script nonce="r4nd0m" integrity="sha384-X" src="//good.com/good.js">
I have a server-side-rendered React app and Node/Express so far were able to generate the correct, stable ETags, allowing for taking advantage of client-side caching.
Additionally, generated HTML contains fragments of render-blocking (above-the-fold) CSS and JS inlined as <script> and <style> tags for faster client-side first renders (as promoted by Google and its PageSpeed and Lighthouse tools).
Now I want to enable Content Security Policy (CSP) and I provide a nonce as an attribute to those <script> and <style> tags on every page request, to avoid unsafe-inline violations. However, ever-changing nonce makes ETags to change on every request as well. HTML is never cached and every request hits my Express server.
Is there a way to combine simultaneously:
inlined CSS and JS
CSP features (that is nonce, or similar)
ETags or alternatives
?
So far I see a contradiction between current performance vs security guidelines.
Are there equivalents to CSP nonce or can CSP nonce be provided while keeping HTML intact? Is there a way to otherwise cache pages that contain CSP nonce?
Ideally, I would like a solution to be contained within the Express server, without resorting to tinkering with my reverse proxy config, but any options are welcome.
One solution is to leave the whole content generation and caching to web application (Node in your case) and CSP nonce generation to front-end webserver (e.g. Nginx). I have implemented it with Django which does page caching with ETag, does all the Vary header logic etc and the HTML it produces contains such a static CSP nonce placeholder:
< script nonce="+++CSP_NONDE+++"> ... </script>
This placeholder is then filled in by Nginx using ngx_http_subs_filter_module:
sub_filter_once off;
sub_filter +++CSP_NONCE+++ $ssl_session_id;
add_header Content-Security-Policy "script-src 'nonce-$ssl_session_id'";
I have seen solutions using an additional Nginx module to generate a truly unique random nonce for each request but I believe it's an overkill and I'm just using TLS session identifier, which is unique per each connecting client and may be cached for some time (e.g. 10 minutes) depending on your Nginx configuration.
Just make sure the web application returns uncompressed HTML as Nginx won't be able to do string substitution.
How to cryptographically verify web page requisites in HTML?
For example, if I have some external resource like an image, a style sheet or (most importantly) a script on a (potentially untrusted) content delivery network, is it possible to force the client browser to cryptographically verify the hash of the downloaded resource before usage? Is there some HTML attribute or URL scheme for this or does one manually have to write some JavaScript to do it?
The rationale is that providing the hashes in HTML served over HTTPS provides an extra defence against compromised (or faulty) CDN-s.
Related questions on SO:
How secure are CDNs for delivering jQuery?
As of 23 June 2016 Subresource Integrity is a W3C Recommendation which allows you to do just that (draft version here). According to the Implementation Report it is already implemented in Firefox 43 and Chrome 45.
A simple example using subresource integrity would be something like:
<script src="https://example.com/example.js"
integrity="sha256-8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts="
crossorigin="anonymous"></script>
It is also possible to specify multiple algorithm-hash pairs (called metadata) in integrity field, separated by whitespace and ignoring invalid data (§3.3.3). The client is expected to filter out the strongest metadata values (§3.3.4), and compare the hash of the actual data to the hash values in set of the strongest metadata values (§3.3.5) to determine whether the resource is valid. For example:
<script src="https://example.com/example.js"
integrity="
md5-kS7IA7LOSeSlQQaNSVq1cA==
md5-pfZdWPRbfElkn7w8rizxpw==
sha256-8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts=
sha256-gx3NQgFlBqcbJoC6a/OLM/CHTcqDC7zTuJx3lGLzc38=
sha384-pp598wskwELsVAzLvb+xViyFeHA4yIV0nB5Aji1i+jZkLNAHX6NR6CLiuKWROc2d
sha384-BnYJFwkG74mEUWH4elpCm8d+RFIMDgjWWbAyaXAb8Oo//cHPOeYturyDHF/UcnUB"
crossorigin="anonymous"></script>
If the client understands SHA256 and SHA384, but not MD5, then it tokenizes the value of the integrity attribute by whitespace and throws away the md5- metadata tokens as garbage. The client then determines that the strongest hashes in the metadata are SHA384 and compares their values to the SHA384 hash of the actual data received.
I assume the browser contacts the web server and asks for the "src" (in those situations where there's something to src).
Can that interaction be controlled in any way?
How much information is available to the server about who wants the src and when?
Alternatively, could one deliberately 404 the request, then control the 404 mechanism to respond appropriately?
Don't mess around with 404 handling for this. If you want to dynamically generate javascript there's no need.
The browser doesn't care what URL is in the src="" attribute - it certainly doesn't have to end in .js. The important thing is that whatever the URL is, it should return its content with the content-type application/javascript.
So the simplest thing to do is put the path to a PHP (if that's what you're using) file and just ensure that what's returned is valid Javascript, sent with a correct Content-Type HTTP header
Scripts specified via a src attribute are handled just like any other resource on a page. If you return a 404 code, the browser won't bother trying to deal with the server further for that resource. The server gets all of the usual HTTP request information (assuming the browser sends it normally), and the Referrer: header is set to the page which is including the resource.