alf.nu / @steike

ServiceWorker is dangerous

The latest version of Chrome enables ServiceWorker support, and allows some fun new attacks.

ServiceWorker lets JavaScript code running on some origin register a handler for some part of the URL space of that origin; any subsequent requests made by the browser will be passed through the handler.

Intuitively, this should not be very useful to an attacker -- if they have XSS on a domain, the game is already lost -- but it becomes more interesting when the site uses sandbox domains.

Sandbox domains

The basic conflict of web security is that your web application wants to store and present user data, but the browser wants to execute everything it sees.

A common way to stay out of trouble is to quarantine unfiltered user-generated content to a separate uncookied domain (if the user is logged in to example.com, serve the content from userfiles.example.net). If the browser gets antsy and wants to execute some user files, it can do so, but the code will be running in the userfiles.example.net origin, where there are no cookies to abuse.

ServiceWorker

With ServiceWorker, an attacker can install a permanent 'rootkit' on the sandbox domain, and watch all future requests. This is bit of a problem if the file names were supposed to be secret.

Installing a ServiceWorker requires, besides JavaScript running on the victim domain, a file with a text/javascript content type, like this:

test.js
self.addEventListener('fetch', function(e) {
  e.respondWith(new Response(
          new Blob(
            ["<h2>I'm in your browser, ",
       	     "stealing your files</h2>\n"],
            {type : 'text/html'})));
});

It's installed like this:

function install() {   // Click to run: 

  return checkBrowser(1).then(function() {
    return navigator.serviceWorker.register(
      '/ServiceWorker/test.js?'+Math.random(),
      { scope:'/ServiceWorker/scope' }
    )
  }).then(function(r) {
    mark(' Installed!');
    inline().value = this.r = r;
    duck.location.href = 'https://alf.nu/ServiceWorker/scope/somewhere.html?x=' + Math.random();
  });
}

If it is installed correctly, reloading this test frame should show it:

https://alf.nu/ServiceWorker/scope/somewhere.html

Dropbox

(Dropbox exploit no longer works; Dropbox sends 403 when the Service-Worker header is present)

What to do

If you run a site that serves user files with secret URLs from a shared domain, you need to look out for the Service-Worker: script HTTP header; if you see it, run for the hills.

If you are a browser vendor, please consider making scary new features opt-in.

Vendor response

Reported to Google and Dropbox Dec 6 2014, with a working demo.

Google fixed the %2F issue, but recommends every site using sandbox domains add extra code to protect against this.

Dropbox never responded, but eventually added protection.

Complaints to @steike or @steike.