Symbolbild Schutz: Rotes-Gelbes Schild

Die Subresource Integrity (SRI) ist ein wichtiger Bestandteil zur Sicherheit von Webseiten

Die Subresource Integrity (SRI) ist ein Sicherheitsverfahren, das davor schützt, nachträglich veränderte Scripte oder CSS-Dateien in Webseiten zu laden.

Dabei wird auf Hash-Werte zurückgegriffen die eine geladene Datei eindeutig identifizierbar macht.

D. h.: entspricht der angegebene Hash nicht dem der externen Datei, wird diese nicht geladen.
Man erhält dadurch immer genau die Version der Datei, die man aufgrund des Hashes erwartet.

Angenommen, die externe Ressource wurde geändert

3. User Agent verweigert die Datei
1. Anforderung einer Ressource mit SRI-Hash >
Server mit kompromittierten Dateien.
< 2. Server liefert Datei mit falschem Hash.

Überprüfung der SRI einer Webseite

Das einfachste Mittel zum Überprüfen der SRI einer Seite ist die Webseite Dort können Sie eine URL eingeben und sehen, ob alle externen Scripte oder CSS-Dateien mit SRI geladen wurden.
Screenshot: Kein RSI Fehler
Mozilla-Observatory Screenshot: Dateien mit SRI geladen.
Screenshot: RSI Fehler
Mozilla-Observatory Screenshot: Dateien nicht mit SRI geladen.

Implementierung auf der Webseite

integrity
Hier folgt nach der Angabe des Hash-Algorithmus (als Präfix), getrennt durch einen „-“, der base64 kodierte Hash.

integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
    

Es können hier mehrere Hashes angeben werden. Diese werden durch ein Leerzeichen getrennt.

<script src="/hello_world.js"
	integrity="sha384-H8BRh8j48O9oYatfu5AZzq6A9RINhZO5H16dQZngK7T62em8MUt1FLm52t+eX6xO
              sha512-Q2bFTOhEALkN8hOms2FKTDLy7eugP2zFZ1T8LCvX42Fp3WoNr3bjZSAHeOsHrbV1Fu9/A0EzCinRE7Af1ofPrw=="
	crossorigin="anonymous">
</script>
    
In diesem Fall wählt der User-Agent die stärkste Hash-Funktion aus, um die Datei zu überprüfen.

Konforme User-Agents müssen die Hash-Funktionen sha256, sha384 und sha512 unterstützen.
crossorigin

crossorigin="anonymous"
    

Wenn die Anfrage nicht den gleichen Ursprung hat, muss hier anonymous angegeben werden. Ist dies nicht der Fall, behandelt der Browser die Datei, als ob das Integritätsattribut nicht gesetzt ist. Dadurch geht die Sicherheit durch SRI wieder verloren.

Erstellen einer SRI

Online

Die Hashes können z. B. auf der Seite SRI Hash Generator erzeugt werden.

Offline / Direkt

Verschiedene Methoden zum Erzeugen des Hashes

cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A

shasum -b -a 384 FILENAME.js | awk '{ print $1 }' | xxd -r -p | base64

<?php
function checksum($input) {
    $hash = hash('sha256', $input, true);
    $hash_base64 = base64_encode($hash);
    return "sha256-$hash_base64"; }
?>

CDN Anbieter

CDNs wie z. B. jsDelivr bieten die Möglichkeit, die SRI automatisch zu erzeugen:
Screenshot: SRI jsDelivr
jsDelivr Screenshot: Auswahl mit SRI.

Automatische Erzeugung

Eine leider oft gezeigte Methode, die Hashes, z. B. über PHP, automatisch zu erzeugen ist folgende:

<?php
$data = file_get_contents("https://code.jquery.com/jquery-3.6.0.min.js");
echo base64_encode(hash("sha256", $data, true));
>

Mit dieser Methode wird der Sicherheitsmechanismus der SRI ausgehebelt. Damit lässt sich nicht mehr feststellen, ob die Ressource kompromittiert ist, da der User-Agent keinen Vergleich hat, sondern nur den Hash der externen Datei und dieser wird immer stimmen.
Der Hash muss bei so einer Vorgehensweise nicht von der externen, sondern von einer sicheren lokalen Ressource erzeugt werden.
Rein aus Performancegründen sollte dies nicht bei jedem Seitenaufruf geschehen, sondern, nur wenn sich die Dateien geändert haben.

Fallback

Sollte das Laden der externen Ressource fehlschlagen, ist es sinnvoll, auf eine lokale Kopie zurückzugreifen.

<script>
window.jQuery ||
	document.write(
	'<script window.jQuery || document.write('<script src="/js/jquery.min.js"><\/script>');
</script>
    

Im Zusammenhang mit einer Content-Security-Policy (CSP) sollte das vorherige Beispiel nicht lauffähig sein, da hier ein Inline-Script erzeugt wird. Ein unsafe-inline, in der CSP, sollte bei Scripten vermieden werden.
Deshalb fügt man hier eine passende nonce ein:

<script nonce="anF1ZXJ5ZmsbGJhY2s=">
window.jQuery ||
	document.write(
	'<script window.jQuery || document.write('<script src="/js/jquery.min.js"><\/script>');
</script>
    
und passt die CSPs entsprechend an:

default-src 'none';
script-src 'nonce-anF1ZXJ5ZmsbGJhY2s=';
connect-src 'self';
img-src 'self';
style-src 'self';
base-uri 'self';
form-action 'self'; 

Alternativ kann man auch ein Script wie Subresource Integrity Fallback verwendet. Dieses lädt im Fehlerfall die lokale Ressource.
Das Script muss vor allen anderen Ressourcen geladen werden.

<script
	src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"
	integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
	data-sri-fallback="/js/jquery.min.js"
	crossorigin="anonymous">
</script>
    
Mit dem Data-Attribute data-sri-fallback wird hier die lokale Datei angegeben.

Dieses Script muss lokal vorhanden sein, sonst funktioniert bei einem CDN-Fehler auch dieses nicht.

Weitere Beispiele

Für CSS-Dateien:

<link
	href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css"
	rel="stylesheet"
    integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x"
    crossorigin="anonymous">

Test einer SRI

Wenn Sie eine SRI das erste Mal auf Ihrer Seite einsetzen, sollten Sie anschließend folgendes überprüfen:
  1. Gibt es Fehlermeldungen in der Browser-Konsole?
  2. Sind noch alle Funktionen der Seite gegeben?

Fehlermeldung in der Browser-Konsole

Screenshot: SRI-Fhler
FireFox Browser-Konsole Screenshot: Fehler mit SRI.
Screenshot: SRI-Fhler
Edge Browser-Konsole Screenshot: Fehler mit SRI.

Zusammenfassung

SRI über HTTP bringt wenig Nutzen, da die Übertagung beeinflusst werden kann. SRI ist nur im Zusammenspiel mit HTTPS sinnvoll.
SRI kann, was CSP und HTTPS nicht können: Überprüfen, ob auch der richtige Inhalt geladen wird.

Checkliste

  • Jede externe Ressource (CSS oder Script) hat ein passendes integrity Attribut.
  • crossorigin="anonymous", sonst wird der Hash nicht überprüft.
  • Der Hash muss von einer bekannten, sicheren Quelle stammen.
  • Bei einer Änderung der externen Ressource / Quelle muss der Hash neu erzeugt werden!

Mehr zum Thema

Tools

Weiterführende Informationen