Unterressourcenintegrität verstehen
Veröffentlicht: 2022-03-10 Wenn Sie jemals eine vom CDN gehostete Version einer JavaScript-Bibliothek verwendet haben, ist Ihnen möglicherweise ein seltsam aussehendes integrity
im script-Tag aufgefallen. Dieses Attribut enthält scheinbar endlosen alphanumerischen Müll, den Sie möglicherweise auf der Suche nach sauberem Code entfernen möchten.
All dieser Müll ist eigentlich eine wirklich nützliche Sicherheitsfunktion namens Subresource Integrity (SRI), die helfen kann, Ihre Website gegen bestimmte Arten von Hacks und Kompromittierungen zu schützen. In diesem Artikel werfen wir einen Blick darauf, was SRI ist, wie es Sie schützen kann und wie Sie es in Ihren eigenen Projekten verwenden können, nicht nur für Dateien, die auf CDNs gehostet werden.
Ein bisschen Geschichte
Vor langer Zeit, als JavaScript der ärmere Cousin von HTML und CSS war, mussten wir uns nicht allzu viele Gedanken darüber machen, wie unsere Skripte als Angriffsvektor für unsere Websites verwendet werden könnten. Die meisten Websites wurden alle auf einem einzigen physischen Server irgendwo in unserer eigenen Hosting-Infrastruktur gehostet, und es war der Server, an dessen Verteidigung wir dachten, wenn es um Best Practices für die Sicherheit ging.
Als die Browser leistungsfähiger und die Internetverbindungen dicker wurden, fingen wir an, mehr und mehr JavaScript zu verwenden, und schließlich begannen wiederverwendbare JavaScript-Bibliotheken aus dem Boden zu schießen. In diesen frühen Tagen wurden Bibliotheken wie script.aculo.us, Prototype und schließlich jQuery von Entwicklern angenommen, die ihre Seiten mit mehr Interaktivität ausstatten wollten.
Mit diesen hinzugefügten Bibliotheken und nachfolgenden Plugins wurde die Seitenlast erhöht, und bald begannen wir ernsthaft über die Front-End-Leistung nachzudenken. Ressourcen wie Content Delivery Networks (CDNs), die zuvor riesigen Unternehmen vorbehalten waren, wurden für den Alltagsnutzer, der schnelle Websites erstellte, alltäglich.
Unterwegs bemerkte ein heller Funke, dass Websites alle ihre eigenen Kopien gängiger Bibliotheken anforderten – Dinge wie die neueste jQuery – und wenn es eine gemeinsame CDN-Version dieser Bibliotheken gäbe, die von jeder Website verwendet werden könnte, dann würde der Benutzer Sie müssen nicht immer dieselbe Datei herunterladen. Sie würden den Treffer für die erste Site nehmen, die die Datei verwendet, aber dann würde sie in ihrem lokalen Browser-Cache gespeichert und Downloads könnten für jede nachfolgende Site übersprungen werden. Genius!
Aus diesem Grund sehen Sie CDN-Links für Ihre bevorzugten Bibliotheken, die URLs wie jsdelivr.com
– sie verwenden ein gemeinsames CDN, um die Dateien zu hosten, damit ihre Benutzer die Leistungsvorteile sehen.
Was könnte schiefgehen?
Dies bleibt eine gute, praktische Arbeitsweise, führt jedoch zu einem potenziellen Angriffsvektor. Stellen wir uns vor, es ist 2012 und alle verwenden das brandneue jQuery 1.8. Zurück zur traditionellen Vorgehensweise hätte jeder seine eigene jQuery 1.8-Datei, die als Teil seiner eigenen Website auf seinem eigenen Server gehostet wird.
Wenn Sie eine Art böser Akteur wären – wie eine Art jQuery-basierter Hamburglar – und einen hinterhältigen Weg gefunden hätten, die Bibliothek für Ihre eigenen bösen Gewinne zu hacken, müssten Sie jede Website einzeln angreifen und ihre Server kompromittieren irgendwelche Auswirkungen. Das ist viel Aufwand.
Aber so sind die Dinge jetzt nicht, da jeder jQuery verwendet, das von einem gemeinsamen CDN geladen wird. Und wenn ich alle sage, meine ich nicht Hunderte von Webseiten. Ich meine Millionen von Webseiten. Plötzlich ist diese eine Datei ein sehr attraktives Ziel für unseren zwielichtigen Hacker geworden. Wenn sie diese eine Datei kompromittieren können, können sie sehr schnell Code auf Millionen von Webseiten auf der ganzen Welt ausführen lassen.
Es spielt keine Rolle, was dieser Code ist. Es könnte ein Streich sein, um Seiten zu verunstalten, es könnte ein Code sein, um Ihre Passwörter zu stehlen, es könnte ein Code sein, um Kryptowährung abzubauen, oder es könnten hinterhältige Tracker sein, die Ihnen im Internet folgen und ein Marketingprofil erstellen. Wichtig ist, dass die unschuldige Datei, die der Entwickler einer Seite hinzugefügt hat, geändert wurde und Sie jetzt ein bösartiges JavaScript als Teil Ihrer Website ausführen. Das ist ein großes Problem.
Geben Sie Subressourcenintegrität ein
Anstatt die Uhren zurückzudrehen und eine nützliche Methode zur Verwendung von Code aufzugeben, ist SRI eine Lösung, die ein einfaches Sicherheitsniveau hinzufügt. SRI und das integrity
stellen sicher, dass sich die Datei, die Sie mit einer Seite verknüpft haben, nie ändert. Und wenn es sich ändert, wird es vom Browser abgelehnt.
Zu überprüfen, ob sich Code nicht geändert hat, ist ein sehr altes Problem in der Informatik und glücklicherweise hat es einige sehr gut etablierte Lösungen. SRI leistet gute Arbeit bei der Übernahme des Einfachsten – Datei-Hashing.
Beim Datei-Hashing wird eine Datei genommen und durch einen Algorithmus geleitet, der sie auf eine kurze Zeichenfolgendarstellung reduziert, die als Hash oder Prüfsumme bezeichnet wird. Ohne ins Unkraut zu geraten, ist der Prozess entweder wiederholbar oder umkehrbar, so sehr, dass, wenn Sie jemand anderem eine Datei zusammen mit dem Hash geben würden, sie denselben Algorithmus ausführen könnten, um zu überprüfen, ob die beiden übereinstimmen. Wenn sich die Datei oder der Hash ändert, gibt es keine Übereinstimmung mehr und Sie wissen, dass etwas nicht stimmt, und sollten der Datei misstrauen.
Wenn Sie SRI verwenden, enthält Ihre Webseite den Hash und der Server (CDN oder irgendwo) enthält die Datei. Der Browser lädt die Datei herunter und berechnet dann schnell, um sicherzustellen, dass sie mit dem Hash im integrity
übereinstimmt. Bei Übereinstimmung wird die Datei verwendet, andernfalls wird sie gesperrt.
Ausprobieren
Wenn ich heute zu getbootstrap.com
gehe, um einen CDN-Link zu einer Version von Bootstrap zu erhalten, bekomme ich ein Tag, das so aussieht:
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
Sie können sehen, dass das Attribut src
so ist, wie wir es gewohnt sind, und das Attribut integrity
enthält, was wir jetzt als Hash kennen.
Der Hash besteht eigentlich aus zwei Teilen. Das erste ist ein Präfix, um anzugeben, welcher Hash-Algorithmus verwendet werden soll. In diesem Fall ist es sha384
. Darauf folgt ein Bindestrich und dann der Hash selbst, codiert mit base64
.
Möglicherweise kennen Sie base64
als Methode zum Codieren von Inline-Dateien wie Bildern in Seiten. Es ist kein kryptografischer Prozess – es ist nur eine schnelle und bequeme Möglichkeit, potenziell chaotische Daten so zu codieren, dass sie sauber in ASCII übersetzt werden können. Aus diesem Grund wird es im Internet häufig verwendet.
Wenn der Browser dies sieht, lädt er bootstrap.min.js
herunter. Vor der Ausführung wird der Hash base64
-dekodiert und dann der sha384
Hash-Algorithmus verwendet, um zu bestätigen, dass der Hash mit der gerade heruntergeladenen Datei übereinstimmt. Bei Übereinstimmung wird die Datei ausgeführt.
Ich kann dies testen, indem ich dieses Tag in eine Seite einfüge und dann in meinen Browser-Tools zur Registerkarte Netzwerk blättere, um zu sehen, dass die Datei geladen wurde.
Ich kann sehen, dass bootstrap.min.js
(und auch die benötigte jQuery-Datei) erfolgreich geladen wurden.
Mal sehen, was passieren würde, wenn ich den Hash so aktualisiere, dass er etwas ist, von dem ich weiß, dass er falsch ist.
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-SmashingMagazineIsCoolForCats" crossorigin="anonymous"></script>
Wie Sie sehen können, stimmt der auf meiner Seite angegebene Hash nicht mehr mit der Datei überein, sodass die Datei blockiert wird.
Verwenden von SRI in Ihren eigenen Projekten
Diese Funktion für Bibliotheken auf einem CDN zu haben, ist großartig, und wenn Sie die Option sehen, eine eingebettete Datei mit einem integrity
zu verwenden, sollten Sie diese Option auf jeden Fall bevorzugen. Aber es ist nicht auf große Projekte auf CDNs beschränkt, Sie können dies selbst für Ihre eigenen Websites verwenden.
Es ist überhaupt nicht weit hergeholt, sich ein Szenario vorzustellen, in dem es einem Hacker gelingt, sich Zugriff auf nur wenige Dateien auf Ihrer Website zu verschaffen. Ich denke, die meisten von uns haben schon einmal einen Kunden, Kollegen oder Freund gesehen, der irgendwann eine WordPress-Seite mit einer Menge bösen Mülls kompromittiert hatte, von dem sie nicht einmal wussten, dass es dort war.
Auch davor kann SRI Sie schützen. Wenn Sie Integritäts-Hashes für Ihre eigenen Dateien generieren, kann Ihre Site alle Änderungen ablehnen, genau wie bei einer remote gehosteten Datei.
Hashes generieren
Sie können erwartungsgemäß einige Befehle am Terminal Ihres Computers ausführen, um einen Hash für eine Datei zu generieren. Dieses Beispiel dafür stammt von der MDN-Unterressourcen-Integritätsseite:
cat FILENAME.js | openssl dgst -sha384 -binary | openssl base64 -A
Das heißt, den Inhalt von FILENAME.js
und als Eingabe an openssl
übergeben, um mit sha384
einen Digest zu erstellen, der dann als Eingabe an einen anderen openssl
-Befehl übergeben wird, um das Ergebnis mit base64
zu codieren. Das ist nicht nur kompliziert und undurchsichtig, sondern auch nicht das, was Sie jedes Mal von Hand tun möchten, wenn sich Ihre JavaScript-Datei ändert.
Nützlicher ist es, wenn Sie dies irgendwie in den Erstellungsprozess Ihrer Website integrieren möchten, und wie Sie sich vorstellen können, gibt es dort viele vorgefertigte Optionen. Die genaue Implementierung wird je nach Projekt stark variieren, aber hier sind einige Bausteine.
Wenn Sie Gulp zum Erstellen Ihrer Websites verwenden, gibt es gulp-sri, das eine JSON-Datei mit einer Liste Ihrer Dateien und ihrer Hashes ausgibt. Sie können dies dann auf Ihrer Website verwenden. Beispielsweise könnten Sie für eine dynamisch gerenderte Website ein Vorlagen-Plugin erstellen, um diese Datei zu lesen und die Hashes bei Bedarf zu Ihren Vorlagen hinzuzufügen.
Wenn Sie immer noch bei Gulp sind, aber eine statische Site (oder eine statisch generierte Site) haben, können Sie gulp-sri-hash verwenden, das Ihre HTML-Seiten tatsächlich durchläuft und die Seiten ändert, um bei Bedarf Hashes hinzuzufügen, was sehr praktisch ist.
Wenn Sie Webpack verwenden, gibt es eine Webseiten-Unterressourcen-Integrität, die im wahren Webpack-Stil komplexer ist, als jeder Mensch es erwarten würde, aber anscheinend funktioniert.
Für diejenigen, die die Handlebars-Template-Engine verwenden, scheinen Ihnen Optionen zur Verfügung zu stehen, und wenn Ihr Build-Prozess nur einfaches JavaScript ist, gibt es auch dort einfache Lösungen.
Wenn Sie ein CMS wie WordPress verwenden, habe ich ein Plugin gefunden, das es scheinbar einfach macht, obwohl ich es selbst nicht ausprobiert habe. Wenn Sie mit SRI oder Sub Resource Integrity nach Ihrer eigenen Plattform Ihrer Wahl googeln, werden Sie wahrscheinlich in die richtige Richtung weisen.
Im Wesentlichen möchten Sie Ihren Hash einhängen, nachdem Ihre JavaScript-Dateien minimiert wurden, und diesen Hash dann auf irgendeine Weise für jeden Teil Ihres Systems verfügbar machen, der die <script>
-Tags ausgibt. Eines der Wunder der Webplattform ist, dass sie technisch so vielfältig ist, aber deshalb kann ich Ihnen leider keine guten Implementierungsanweisungen geben!
Andere Dinge zu beachten
In diesem Artikel habe ich viel über JavaScript-Dateien gesprochen, weil es dort wirklich am sinnvollsten ist, sich gegen Hacking-Angriffe zu verteidigen. SRI funktioniert auch mit CSS, sodass Sie es dort genauso verwenden können. Das Risiko für böswilliges CSS ist viel geringer, aber das Potenzial, eine Website zu verunstalten, besteht immer noch, und wer weiß, welche Browserfehler auch dazu führen können, dass CSS Ihre Website versehentlich einem Hacker aussetzt. Es funktioniert also auch dort mit SRI.
Eine weitere interessante Sache, die Sie tun können, ist die Verwendung einer Inhaltssicherheitsrichtlinie, um anzugeben, dass alle Skripte (oder Stile) auf Ihrer Seite SRI verwenden müssen , und dass SRI natürlich validiert werden muss.
Content-Security-Policy: require-sri-for script;
Auf diese Weise kann sichergestellt werden, dass SRI immer verwendet wird, was auf Websites nützlich sein kann, an denen mehrere Teammitglieder arbeiten, die mit der Vorgehensweise möglicherweise auf dem neuesten Stand sind oder nicht. Auch hier ist ein guter Ort, um mehr darüber zu lesen, die immer großartige MDN-Dokumentation für Subresource Integrity.
Das Letzte, worüber es sich zu sprechen lohnt, ist die Browserunterstützung für SRI. Die Unterstützung in modernen Browsern ist breit gefächert, mit der Hauptausnahme Internet Explorer. Aufgrund der abwärtskompatiblen Umsetzung der Spezifikation ist diese jedoch sofort einsatzbereit. Browser, die das integrity
verstehen, verwenden den Hash und prüfen die Integrität, und ältere Browser machen einfach weiter wie bisher und arbeiten weiter. Natürlich erhalten Sie in diesen älteren Browsern keinen zusätzlichen Schutz, aber in den Browsern, die Unterstützung bieten.
Fazit
Wir haben nicht nur gesehen, was diese seltsamen Hashes in den integrity
bewirken, sondern auch, wie wir sie verwenden können, um uns gegen bestimmte Arten von Angriffen auf unsere Website zu verteidigen. Natürlich gibt es keine Wunderwaffe, die unsere Sites gegen jede Art von Exploit schützt, aber Subresource Integrity ist ein wirklich nützliches Tool in der Kette.
Beim Ausnutzen einer Sicherheitslücke geht es oft darum, mehrere kleine Teile in eine Reihe zu bringen. Wenn A vorhanden ist und Sie B verwirklichen können, dann macht ein Fehler in C D möglich. Browserfunktionen wie SRI geben uns eine gute Möglichkeit, die Dinge ein wenig mehr zu binden und möglicherweise diese Kette zu durchbrechen und zu verhindern, dass ein Hacker bekommt, was er will. Wenn Sie es in Ihren Build-Prozess oder Ihr CMS integrieren können, sollten Sie es außerdem einmal einrichten und dann vergessen können, und es wird Ihnen keine alltäglichen Unannehmlichkeiten bereiten.
Daher würde ich wirklich empfehlen, sich ernsthaft mit Subresource Integrity zu befassen und es auf Ihren Websites zu implementieren, wenn Sie können.