Subresource Integrity: How to show only warning but not block resource?
Asked Answered
A

2

7

I would like to make a soft integration for Subresource Integrity attributes, so be sure that I did not break the application, but only to show a warning that I need to fix some places.

Is there an option to do so?

Articulate answered 26/3, 2019 at 15:8 Comment(1)
A
6

Secure approach

If you need some kind of flexibility, then you should use a fallback mechanism - loading required resource from another URL. Probability that two different URL's will be hacked at the same time is a lot smaller compared to hacking just one resource. Fallback doesn't violate site security, because you must trust your known-good sources which you use in your code. If your resource is a Javascript - you can use a noncanonical-src attribute for a fallback too.

Insecure approach

Now, if you really, really want a user to break server and/or client security by forcing compromised resource load - at least ask a user if he/she takes responsibility by doing so. Of course this will still be a stupid thing, it's like asking "Would you like to run a virus in your computer ?". I bet nobody would like to say YES. Anyway, here is the code, which does asking these type of questions:

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script>
  <script>
  function loadResource(path) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        var cs = CryptoJS.SHA256(this.responseText);
        if (btoa(cs) == 'NjBiMTllNWRhNmE5MjM0ZmY5MjIwNjY4YTVlYzExMjVjMTU3YTI2ODUxMzI1NjE4OGVlODBmMmQyYzhkOGQzNg==' ||
            confirm('Bootstrap is NOT the latest version 4.3.1, load anyway ?')
           ) {
          var link = document.createElement('link');
          link.rel = "stylesheet";
          link.href = path;
          document.head.appendChild(link);
        }
        else {
           var err = document.getElementById('error');
           err.title = "Component version error !";
           err.innerHTML = '&nbsp;⚠️';
        }
      }
    };
    xhttp.open("GET", path, true);
    xhttp.send();
  }

  loadResource(
              //'https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css' // newest boostrap
              'https://stackpath.bootstrapcdn.com/twitter-bootstrap/2.0.4/css/bootstrap-combined.min.css' // old legacy
              );
  </script>

DEMO

Airway answered 2/4, 2019 at 9:25 Comment(0)
N
1

I do not recommend only displaying warnings when the SRI-Hashes don't match. When see the warning as a User, it's already too late and potentially malicious scripts were executed on your machine.

However, you can implement your desired behaviour using the ServiceWorker-API and something like <script data-integrity="xxxxxxxx">. For that, you'd want to:

  1. Register a new ServiceWorker
  2. Listen to the fetch event
  3. [Client.postMessage] the targetURL to your Parent
  4. Get script integrity hash by targetURL $('script[src=event.data.targetURL]').attr('data-integrity')
    and push it into the client using Worker.postMessage
  5. hash the response using e.G. cryptojs.sha256
  6. match the hashes inside the worker
  7. If the hashes match, return the response. If they don't match, return the response and use Client.postMessage again to trigger a warning.
Negotiate answered 1/4, 2019 at 14:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.