Go-ipfs: [gateway] ServiceWorker could take control over gateway endpoints

Created on 30 Jun 2017  Â·  8Comments  Â·  Source: ipfs/go-ipfs

Version information: 0.4.10-4679f80

Type: Bug

Severity: Low. Not currently a security issue, but could become one in the future.

Description:

Take a look at QmaEtDG87K69mVR7sc48DemHpj3LqxKaQfDw6qJr2AGbmZ:

<!doctype html>
<script>
  navigator.serviceWorker.register('/ipfs/QmRcqyy8yFsVhgErobYrTcF5PSQHC36TqpA19xnBkQpFcB');
</script>

The requested ServiceWorker file is the following:

self.oninstall = event => event.waitUntil(self.skipWaiting());
self.onactivate = event => event.waitUntil(self.clients.claim());
self.onfetch = event => event.respondWith(new Response('All my base are belong to us.'));

This currently does not work for only one reason: The Content-Type on the ServiceWorker file is
not application/javascript but text/plain. If it was set to application/javascript, I could
do the following:

  1. Make someone to visit https://gateway.ipfs.io/ipfs/QmaEtDG87K69mVR7sc48DemHpj3LqxKaQfDw6qJr2AGbmZ
  2. My ServiceWorker would be installed
  3. All subsequent requests to anything that starts with https://ipfs.io/ipfs/ will return ‘All my base are belong to us.’. Even worse, since the introduction of Foreign-Fetch ServiceWorker, even websites using the CORS-enabled gateway.ipfs.io endpoint would receive the same response.

Currently, the Go FileServer implementation, which the gateway uses, does not sniff JavaScript to set a Content-Type: application/javascript header. If they ever change that, or IPFS exposes control over Content-Type, the gateway would become vulnerable to the attack above.

I think ServiceWorker are powerful and they should be allowed on IPFS. ServiceWorker are scoped to
the path where the ServiceWorker file is located. Most of the time it would be located at paths
like /ipfs/<HostID>/serviceworker.js, and therefore be in control of all requests to /ipfs/<HostID>/... which is entirely reasonable.

There’s currently no way to completely disable ServiceWorker for a domain or a path, so I created an issue on the ServiceWorker spec. For the time being, my suggestion is to sett the header Service-Worker-Allowed: /_jail on all requests that match ^/ip[fn]s/[^/]+$ on the gatway.

kinbug topigateway topisecurity

Most helpful comment

Just for clarification for anyone who is new to Service Workers (me), I was initially confused as to why SWs path scope rules wouldn't solve this, but I see now that it doesn't

If you register a SW from:

/ipfs/QmHash/sw.js

then the scopeUrl is /ipfs/QmHash/ and your SW can only manipulate requests for resources below that hash, which is good and proper. But if as in the example you register a SW directly from:

/ipfs/QmHash

and the gateway starts to serve files like that with the correct js mime-type where appropriate, then the browser will have loaded a js file called QmRcqyy8yFsVhgErobYrTcF5PSQHC36TqpA19xnBkQpFcB from the path /ipfs.

In ServiceWorker terms, the scopeUrl ends up being /ipfs/, and that means all other requests for files served from the gateway end up under the control of a potentially malicious ServiceWorkers control.

Of note, path based scopes for service workers were, at least partly, introduced to allow usecases where a service hosts content from multiple users in sibling directories, see: https://github.com/w3c/ServiceWorker/issues/468

Also of note there is an active issue discussing the service worker path scope trailing slash issue and sub origins here: https://github.com/w3c/ServiceWorker/issues/1272

All 8 comments

Hah, very interesting. Thanks for the detective work here :)

We will definitely keep this in mind when moving forward with service worker addons

Thanks for converting the report into this issue and for opening https://github.com/w3c/ServiceWorker/issues/1165 as a proposal!

Putting this on the 0.4.12 milestone so we give it more attention. I know we want to start doing more with service workers and content types, so its important to keep this in mind and follow up.

Happy to help review any idea y’all have in the general area of Service Worker :)

Solution would be to block requests to /ipfs/Qm...AAA with Service-Worker: script header.
Requests to /ipfs/Qm...AAA/xxxx.js should be allowed.

See https://github.com/w3c/ServiceWorker/issues/1165#issuecomment-341688472

I like that solution.

Just for clarification for anyone who is new to Service Workers (me), I was initially confused as to why SWs path scope rules wouldn't solve this, but I see now that it doesn't

If you register a SW from:

/ipfs/QmHash/sw.js

then the scopeUrl is /ipfs/QmHash/ and your SW can only manipulate requests for resources below that hash, which is good and proper. But if as in the example you register a SW directly from:

/ipfs/QmHash

and the gateway starts to serve files like that with the correct js mime-type where appropriate, then the browser will have loaded a js file called QmRcqyy8yFsVhgErobYrTcF5PSQHC36TqpA19xnBkQpFcB from the path /ipfs.

In ServiceWorker terms, the scopeUrl ends up being /ipfs/, and that means all other requests for files served from the gateway end up under the control of a potentially malicious ServiceWorkers control.

Of note, path based scopes for service workers were, at least partly, introduced to allow usecases where a service hosts content from multiple users in sibling directories, see: https://github.com/w3c/ServiceWorker/issues/468

Also of note there is an active issue discussing the service worker path scope trailing slash issue and sub origins here: https://github.com/w3c/ServiceWorker/issues/1272

Just for the record, another vector for this could be future support for returning content-type stored in "Extended Attributes" of https://github.com/ipfs/unixfs-v2/issues/11

Was this page helpful?
0 / 5 - 0 ratings

Related issues

daviddias picture daviddias  Â·  3Comments

Mikaela picture Mikaela  Â·  3Comments

whyrusleeping picture whyrusleeping  Â·  4Comments

ArcticLampyrid picture ArcticLampyrid  Â·  3Comments

djdv picture djdv  Â·  3Comments