What can be done to prevent XSS attacks against IPFS sites?

From @Mithgol on Tue Sep 15 2015 06:59:42 GMT+0000 (UTC)

According to the Open Web Application Security Project, XSS (cross-site scripting) was the third most common Web app vulnerability in 2013.

The current security measures against XSS (such as same-origin policy or content security policy) rely on the centralized nature of the Web, e.g. different domain names mean different ownership of hostnames and thus some types of access are restricted (unless some CSP or CORS settings explicitly say otherwise).

They won’t be effective in IPFS where all data seems to have the same hostname (of its Web gate such as ipfs.io) or becomes a part of the local filesystem.

Then what can be done to prevent XSS attacks against IPFS sites?


Copied from original issue: https://github.com/ipfs/faq/issues/32

1 Like

From @whyrusleeping on Tue Sep 15 2015 23:12:04 GMT+0000 (UTC)

we set CORS headers and restrict origins, see https://github.com/ipfs/go-ipfs/blob/master/core/corehttp/commands.go#L33 and similar.

From @jbenet on Tue Sep 15 2015 23:37:08 GMT+0000 (UTC)

We’ve discussed this a few other places, but we need to pull the information into here.

things worth mentioning/discussing:

1 Like

From @lgierth on Tue Sep 15 2015 23:56:37 GMT+0000 (UTC)

Something that can be done by anyone, without any work on our part, is using a custom domain, as described in https://github.com/ipfs/notes/issues/39

From @Mithgol on Wed Sep 16 2015 06:33:23 GMT+0000 (UTC)

@whyrusleeping CORS is not effective if an IPFS site is attacked by a malicious script that does also reside in IPFS (i.e. an attacker does ipfs add beforehand and then uses the IPFS path of the script) and thus has the same hostname (IP address).

1 Like

From @edrex on Wed Sep 16 2015 18:50:03 GMT+0000 (UTC)

Just to unwrap this

Cause

The root cause of the vulnerability is serving unsanitized resources from mutually-untrusted sources from a single origin.

Attack

  • The user accesses IPFS-deployed App A via the shared gateway.ipfs.io domain, and authorizes some privilege/stores data via that app.
  • Later the user accesses (malicious) App B also via the shared gateway domain. App B is able to use the privileges / access the stored data meant for App A, counter to the user’s expectation of app-level isolation. Targets include:
    • Stored user data
    • Stored credentials for remote services
    • User-approved privileges for “HTML5” APIs such as media capture, storage quota exceptions

Potential resolutions

  • Enforce a separate origin per IPFS/IPNS per “root” node (root: an arbitrary node used as the base/starting point for DAG traversal). Each root represents a trust scope, since all linked objects are fixed at creation time
  • Another resolution, targeting a proposed standard, would be to continue using <gateway.ipfs.io>, but set a per-root suborigin header. See ipfs/go-ipfs#651.
  • The domains (or suborigins) could be <hash>.gateway.ipfs.io or similar, where <hash> is the root node hash encoded using @kyledrake’s hshca.
  • As @lgierth points out, many app publishers will opt to use their own domain which will also close the vulnerability for their app.

References

TiddlyWiki is a venerable distributed publishing system. Various hosting systems for TiddlyWiki content including TiddlySpace use per-application subdomains to prevent XSS attacks.

2 Likes

From @jbenet on Wed Sep 16 2015 22:14:31 GMT+0000 (UTC)

@edrex can you add:

  • implement per-page suborigins in all browsers

to the “resolution” part? TBL recently spoke about this, and it will get more traction. we may see it be standard as soon as next year or the following if we make a big push for it.

1 Like

From @edrex on Wed Sep 16 2015 23:20:20 GMT+0000 (UTC)

@jbenet suborigins per page or per “root”? i could see wanting to share local resources between two pages within the same root, even though “Single Page Apps” are in fashion. Especially since the same page object might get reused under multiple roots, and I think the expectation would be that each usage of a page would be isolated from the others.

How would you ensure security for legacy browsers while serving all gateway content from the same origin with different suborigin header per page (or root)?

From @jbenet on Wed Sep 16 2015 23:56:31 GMT+0000 (UTC)

we would do it per-root.

From @stevearm on Sat Dec 19 2015 21:16:41 GMT+0000 (UTC)

@edrex By “Enforce a separate origin per IPFS/IPNS per “root” node” did you mean having a dns subdomain (<hash>.gateway.ipfs.io)? If so, I think that solution provides:

  • isolation from other pages
  • transferability (the same hash can point to a new version of the page while preserving the same javascript permissions and client-side data)
  • persistence (if the original publisher shuts down all their servers, the page remains functional)

I’ve got a bit more rambling version of this in a blog post

From @kyledrake on Sun Dec 20 2015 00:34:43 GMT+0000 (UTC)

@stevearm I’ve ran into this issue as well. Take a look at https://github.com/neocities/hshca and https://github.com/neocities/hshca-proxy

Per-page origins is coming, but is still a ways off. This is a decent workaround for now.

From @lgierth on Sun Dec 20 2015 03:38:17 GMT+0000 (UTC)

I ordered ipns.name a few a days ago and will deploy HSHCA for IPNS hashes there.

1 Like

From @edrex on Sun Dec 20 2015 07:52:48 GMT+0000 (UTC)

@stevearm, yes, with separate base domains for IPFS and IPNS.

Thanks @kyledrake for thinking through and proposing hshca, it seems reasonable.

Once sub origins are sufficiently baked, we can look at how to support them without compromising security for non-supporting clients.

I’ll be watching https://github.com/ipfs/go-ipfs/issues/651.