子资源完整性:如何只显示警告而不显示块资源?

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

我想为 Subresource Integrity 属性创建一个 soft integration,所以请确保我没有破坏应用程序,但只是为了显示一个警告,我需要修复一些地方。

是否有这样做的选项?

我不建议仅在 SRI-Hashes 不匹配时才显示警告。当以用户身份看到警告时,为时已晚,您的计算机上执行了潜在的恶意脚本。

但是,您可以使用 ServiceWorker-API 和类似 <script data-integrity="xxxxxxxx"> 的方式实现您想要的行为。为此,您需要:

  1. 注册一个新的ServiceWorker
  2. 收听 fetch 事件
  3. [Client.postMessage] 你父级的 targetURL
  4. 通过 targetURL 获取脚本完整性哈希 $('script[src=event.data.targetURL]').attr('data-integrity')
    并使用 Worker.postMessage
  5. 将其推送到客户端
  6. 使用 e.G. 散列响应cryptojs.sha256
  7. 匹配工人内部的哈希值
  8. 如果哈希匹配,return 响应。如果它们不匹配,return 响应并再次使用 Client.postMessage 触发警告。

安全方法

如果您需要某种灵活性,那么您也应该使用 - 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 属性作为备用。

不安全的方法

现在,如果您真的非常希望用户通过强制损害资源加载来破坏服务器 and/or 客户端安全 - 至少询问用户 he/she 是否会为此承担责任。当然,这仍然是一件愚蠢的事情,就像在问“你想运行计算机中的病毒吗?”。我敢打赌没有人愿意说是。不管怎样,这是代码,它确实会问这些类型的问题:

<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