Michael_K: Austausch von ServiceWorker absichern

Hallo,

ich lasse bei einer Web-Applikation über einen ServiceWorker die geladenen Webseiten (requests mit get-methode) im lokalen Cache abspeichern und mit einer CacheFirst Methode wird immer zuerst geschaut, ob die Ressource im lokalen Cache vorliegt und dann genutzt wird. Für den Web Worker selbst ist aber eine Network-First Regel hinterlegt, d.h. es wird geschaut ob eine aktuellere Version des ServiceWorker auf dem Server vorliegt. Mit einer neuen Version des ServiceWorker wird der lokale Cache gelöscht bzw. neu mit den aktuellen Ressourcen der Web Applikation eingelesen.

Ich möchte nun erreichen, dass sichergestellt ist, dass der ServiceWorker nicht einfach so ausgetauscht werden kann. Also das Szenario, dass jemand unbefugt Zugriff auf den Web Server hat und dort den Service Worker kompromitiert und dann unbemerkt die Version bzw. die Ressourcen der WebApplikation austasuchen kann.

Welche sinnvollen Möglichkeiten würde es denn geben, dass man einen Mechanismus implementiert der überprüft, ob der neue ServiceWorker (d.h. JavaScript-Datei) auch legitim ist? Ggfs. würde vielleicht auch schon es ausreichen, wenn der "alte" ServiceWorker davor warnt, das eine neuer Version vorliegt.

Es geht also nicht um ein planmäßiges Update der WebApp sondern um einen "zusätzlichen" Schutz vor unbefugtem Austasuch der Ressourcen.

Ich hoffe, das Problem ist verständlich.

Gruss Michael

  1. Ich möchte nun erreichen, dass sichergestellt ist, dass der ServiceWorker nicht einfach so ausgetauscht werden kann. Also das Szenario, dass jemand unbefugt Zugriff auf den Web Server hat und dort den Service Worker kompromitiert

    In der Regel erreicht man das, in dem der Ersteller der Datei diese mit einem privaten Schlüssel signiert (hoffentlich nicht auf dem Webserver...) und der Nutzer diese Signatur mit einem public key des Erstellers prüft. Dabei sollte man kritisch hinsehen, wenn der für die Prüfung veröffentlichte Public Key sich plötzlich ändert…

  2. Hallo Michael_K,

    ich habe mich vor einiger Zeit mit Serviceworkern beschäftigt. Einerseits, um sie endlich mal im Wki zu tutorisieren, andererseits, weil ich einen Serviceworker beim anstehenden Frickl-Makeover nutzen will, um die Ressourcen für die Frickl-Umgebung für den Frickl-iframe bereitzustellen. Hat auch schon gut geklappt…

    Du schreibst mal Serviceworker und mal Webworker. Das sind zwei verschiedene Dinge. Ein Webworker dient zur asynchronen Verarbeitung von Aufgaben, und ein Serviceworker zur Unterstützung einer Seite im offline-Betrieb, indem die offline benötigten Ressourcen in einem Cache gehalten werden.

    Für den Web Worker selbst ist aber eine Network-First Regel hinterlegt, d.h. es wird geschaut ob eine aktuellere Version des ServiceWorker auf dem Server vorliegt. Mit einer neuen Version des ServiceWorker wird der lokale Cache gelöscht bzw. neu mit den aktuellen Ressourcen der Web Applikation eingelesen.

    Du beschreibst hier das Standardverhalten für Serviceworker. Diese Network-First Regel hast Du nicht selbst erzeugt. Die ist im Browser eingebaut. Oder verstehe ich Dich miss?

    Hier steht:

    An update is triggered if any of the following happens:

    • A navigation to an in-scope page.
    • A functional events such as push and sync, unless there's been an update check within the previous 24 hours.
    • Calling .register() only if the service worker URL has changed. However, you should avoid changing the worker URL.

    "navigation to an in-scope page" ist ziemlich häufig - es wäre ungeschickt vom Browser, bei jeder Seitennavigation die serviceworker.js neu downzuloaden und einen byteweisen Vergleich zu machen. Ich meine, der Browser lädt die Datei aus seinem eigenen Cache, sofern ihr Verfallszeitpunkt noch nicht gekommen ist.

    Der fetch der serviceworker.js läuft aber nicht über den Serviceworker. Das täte mich zumindest sehr wundern. Der Serviceworker registriert sich ja nicht selbst als sein eigener Client. Des weiteren hast Du im Service-Worker - meine ich - auch keinen Zugriff auf die fetch-Inhalte. Du kannst im fetch-Event nur entscheiden, ob Du auf den Cache oder den Server gehst und eine Serverantwort in den Cache schieben. Oder irre ich mich?

    wenn der "alte" ServiceWorker davor warnt, das eine neuer Version vorliegt.

    Das kriegt der gar nicht mit. Der Browser lädt die neue Version und legt sie "auf Halde". Sobald die letzte Seite geschlossen wird, die sich auf die alte Version registriert hat, wird die alte Version beendet und die neue aktiviert.

    Ich muss allerdings auch zugeben, dass ich mit Serviceworker-Updates bisher meine liebe Not hatte. Um sicher zu sein, dass ich eine geänderte .js Datei als Serviceworker lade, musste ich den Worker eigentlich immer manuell über die DevTools löschen - weil die neue Version ja erst aktiv wird, wenn keine Seiten mehr darauf zugreifen.

    Dass Du Dich gegen einen am Server kompromittierten Serviceworker schützen musst, sehe ich als unnötig an. Wenn es jemand schafft, deinem Server eine kompromittierte .js Datei unterzuschieben, hast Du ganz andere Probleme. Ein solcher Jemand dürfte dann auch im Stande sein, deine Signierung auszuhebeln.

    Also das Szenario, dass jemand unbefugt Zugriff auf den Web Server hat und dort den Service Worker kompromitiert

    Dieses Szenario musst Du anders verhindern. Wenn Dir jemand auf dem Webserver Dateien austauschen kann, hast Du ganz andere Probleme.

    Das Szenario, dass der Worker durch eine Man-in-the-Middle Attacke ersetzt wird, wird durch https (begrenzt) verhindert. Wenn auf deinem Client ein Zertifikat liegt, das das Zertifikat des Man-in-the-Middle vertrauenswürdig macht, ist https nur noch Augenwischerei? Gibt's nicht? Doch, schon. Vor allem in Firmen, die per HTTPS-Proxy sicherstellen, dass auf diesem Weg keine Malware hereinkommt und die Angestellten keine VPN Tunnel auf den Heim-PC bauen.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      Du schreibst mal Serviceworker und mal Webworker. Das sind zwei verschiedene Dinge. Ein Webworker dient zur asynchronen Verarbeitung von Aufgaben, und ein Serviceworker zur Unterstützung einer Seite im offline-Betrieb, indem die offline benötigten Ressourcen in einem Cache gehalten werden.

      Das war ein Versehen, ich meine wirklich Service Worker. Die Applikation nutzt zwar auch web worker, aber die Fragestellung bezieht sich auf den Service Worker.

      Du beschreibst hier das Standardverhalten für Serviceworker. Diese Network-First Regel hast Du nicht selbst erzeugt. Die ist im Browser eingebaut. Oder verstehe ich Dich miss?

      Der fetch der serviceworker.js läuft aber nicht über den Serviceworker. Das täte mich zumindest sehr wundern. Der Serviceworker registriert sich ja nicht selbst als sein eigener Client. Des weiteren hast Du im Service-Worker - meine ich - auch keinen Zugriff auf die fetch-Inhalte. Du kannst im fetch-Event nur entscheiden, ob Du auf den Cache oder den Server gehst und eine Serverantwort in den Cache schieben. Oder irre ich mich?

      Das werde ich mal testen, ich hatte nicht angenommen, dass der Service Worker unabhängig ist, d.h. dass man den Service Worker selbst auch cachen kann. Würde aber das Problem mitbringen, dass man sich selbst ausschliessen kann ;-)

      Ich muss allerdings auch zugeben, dass ich mit Serviceworker-Updates bisher meine liebe Not hatte. Um sicher zu sein, dass ich eine geänderte .js Datei als Serviceworker lade, musste ich den Worker eigentlich immer manuell über die DevTools löschen - weil die neue Version ja erst aktiv wird, wenn keine Seiten mehr darauf zugreifen.

      Dafür gibt es doch den Cache-Key. Der Austausch der versionierten Ressourcen funktioniert eigentlich ganz gut

      Also das Szenario, dass jemand unbefugt Zugriff auf den Web Server hat und dort den Service Worker kompromitiert Dieses Szenario musst Du anders verhindern. Wenn Dir jemand auf dem Webserver Dateien austauschen kann, hast Du ganz andere Probleme.

      Das ist mir bewusst und der Server ist schon ziemlich abgesichert (black carbon etc.) Aber es geht mir darum zu verstehen, ob man noch eine Schippe oben drauf legen kann.

      Das Szenario, dass der Worker durch eine Man-in-the-Middle Attacke ersetzt wird, wird durch https (begrenzt) verhindert. Wenn auf deinem Client ein Zertifikat liegt, das das Zertifikat des Man-in-the-Middle vertrauenswürdig macht, ist https nur noch Augenwischerei? Gibt's nicht? Doch, schon. Vor allem in Firmen, die per HTTPS-Proxy sicherstellen, dass auf diesem Weg keine Malware hereinkommt und die Angestellten keine VPN Tunnel auf den Heim-PC bauen.

      Ja, ja, ZScaler & Co ich weiss ,-) Aber Man-in-the-middle ist hier nicht das Scenario. Es geht eher darum, dass überprürt/ischergestellt werden kann, das keiner unbemerkt an der Applikation schraubt. Vermutlich ist wirklich die UpdateNotification, sobald der ServiceWorker sich inhaltlicjh ändert, der einzige sinnvolle Weg.

      Gruss Michael