Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sandbox resources loaded via a path gateway #157

Open
4 tasks
lidel opened this issue Jan 20, 2020 · 7 comments
Open
4 tasks

Sandbox resources loaded via a path gateway #157

lidel opened this issue Jan 20, 2020 · 7 comments
Assignees
Labels
dif/expert Extensive knowledge (implications, ramifications) required effort/weeks Estimated to take multiple weeks kind/question A question or request for support need/analysis Needs further analysis before proceeding P1 High: Likely tackled by core team if no one steps up status/in-progress In progress topic/origin Issues related to Origin-based security
Milestone

Comments

@lidel
Copy link
Member

lidel commented Jan 20, 2020

Motivation

Websites loaded via path gateway are able to access cookies and storage of the entire domain. While we are moving to subdomain gateways (#89), requests made to path gateways will continue to lack origin isolation between content roots. Some will be redirected to subdomain ones, but we should look into other means of improving the situation.

TL;DR

  1. subdomain gateways will provide Origin isolation
  2. path gateways do not
  3. Various headers can be leveraged for limiting what can be used on the origin of path gateway.

Headers to investigate

Clear-Site-Data header

The Clear-Site-Data header clears browsing data (cookies, storage, cache) associated with the requesting website. It allows web developers to have more control over the data stored locally by a browser for their origins.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Clear-Site-Data

We could leverage Clear-Site-Data header and send a hint to user agent to clear any preexisting cookies and storage. This is a "nuclear option", but could incentivize users to switch to subdomain gateways when access Web APIs relying on Origin is required.

Note: this requires native subdomain support (ipfs/kubo#6498) to land first.

To purge cookies and storage without reloading any contexts, below header would be returned with every response from /ipfs/{cid} and /ipns/{foo} paths:

Clear-Site-Data: "cookies", "storage"

Content-Security-Policy

Disabling JS and various security features.

Ref. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy

Highlights:

  • sandbox directive may be the most elegant way, it would apply the same logic as <iframe> sandbox for entire page.

Prior art:

  • blogpost: https://blog.web3.storage/posts/badbits-and-goodbits-csp-in-w3link
  • web3.storage returns:
    • content-security-policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' blob: data: https://*.w3s.link https://*.nftstorage.link https://*.dweb.link https://ipfs.io/ipfs/ https://*.githubusercontent.com https://tableland.network https://*.tableland.network ; form-action 'self'; navigate-to 'self'; connect-src 'self' blob: data: https://*.w3s.link https://*.nftstorage.link https://*.dweb.link https://ipfs.io/ipfs/ https://*.githubusercontent.com https://tableland.network https://*.tableland.network ; report-to csp-endpoint ; report-uri https://csp-report-to.web3.storage
    • reporting-endpoints: csp-endpoint="https://csp-report-to.web3.storage"

Feature-Policy

Another way of disabling various APIs and behaviors

Ref. https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy

TODO

  • create PoC proxy to validate the idea
    • setting Gateway.HTTPHeaders in go-ipfs config may be enough for initial tests
  • document behavior in Firefox (
  • document behavior in Chromium
  • document behavior in Safari
@lidel lidel added kind/question A question or request for support needs clarification status/blocked Unable to be worked further until needs are met topic/origin Issues related to Origin-based security labels Jan 20, 2020
@lidel
Copy link
Member Author

lidel commented Jan 30, 2020

Blocking cookies is a nuclear option that may break some deployments behind reverse proxies that pass all headers. We would need NoWebSecurity flag (false by default) in case someone really wants to disable things like Clear-Site-Data in contexts that provide no origin isolation.

lidel added a commit to ipfs/kubo that referenced this issue Jan 30, 2020
This removes note about Clear-Site-Data.
Tracked in ipfs/in-web-browsers#157

License: MIT
Signed-off-by: Marcin Rataj <[email protected]>
lidel added a commit to ipfs/kubo that referenced this issue Feb 11, 2020
This removes note about Clear-Site-Data.
Tracked in ipfs/in-web-browsers#157

License: MIT
Signed-off-by: Marcin Rataj <[email protected]>
@lidel
Copy link
Member Author

lidel commented Feb 13, 2020

Something to be aware of: executionContexts and wildcard directives are not recognized by Chromium (bug-898503)

lidel added a commit to ipfs/kubo that referenced this issue Mar 4, 2020
This removes note about Clear-Site-Data.
Tracked in ipfs/in-web-browsers#157

License: MIT
Signed-off-by: Marcin Rataj <[email protected]>
@lidel
Copy link
Member Author

lidel commented Mar 19, 2020

Interesting fact: w3c spec suggests a discrepancy between clearing cookies and storage:
https://www.w3.org/TR/2017/WD-clear-site-data-20171130/#grammardef-storage
https://www.w3.org/TR/2017/WD-clear-site-data-20171130/#grammardef-cookies

According to the spec storage is supposed to be purged for origin, while cookies cleanup is listed as origin + all origins based on subdomains of the current one.

I tested behavior in Chromium 76 and Firefox 74 to see if it negatively impacts subdomain gateways in go-ipfs (ipfs/kubo#6096). This does not seem to be the case: subdomain cookies are not purged if Clear-Site-Data is present in localhost/ipfs/$cid 301 response.

@lidel lidel changed the title Clear-Site-Data when loaded via path gateway Disable storage/cookies/WebAPIs when loaded via path gateway Mar 24, 2021
@lidel lidel changed the title Disable storage/cookies/WebAPIs when loaded via path gateway Sandbox resources loaded via a path gateway Mar 24, 2021
@lidel lidel pinned this issue Mar 24, 2021
@lidel lidel self-assigned this Jun 7, 2021
@lidel lidel added P1 High: Likely tackled by core team if no one steps up status/in-progress In progress dif/expert Extensive knowledge (implications, ramifications) required effort/weeks Estimated to take multiple weeks need/analysis Needs further analysis before proceeding and removed status/blocked Unable to be worked further until needs are met needs clarification labels Jun 7, 2021
@lidel
Copy link
Member Author

lidel commented Jun 8, 2021

Sidenote: we could reuse this on locked-down subdomain namespace ipfs/kubo#7318 (think cors.dweb.link/ipfs/) that is optimized for loading data/subresources and not website roots:

  • path gateway
  • has liberal CORS (*)
  • has locked-down web APIs like storage

This could be greatly deduplicated and simplified, ideally, we would introduce everything (hardening path gateways; hardening/removing CORS from subdomains; support for long CIDs; support for CORS without compromising any local storage) in a single PR/release.

@darobin
Copy link
Collaborator

darobin commented Feb 21, 2023

I would like to suggest taking the restrictions on Permissions-Policy (which was called Features-Policy when this issue was opened — @lidel mentions it at the top) further (spec, mdn). When you load a random web page, a number of features are available generally gated by some kind of permission or interaction. That is often okay (or at least it's understood to be a managed risk) but it is open to phishing or other forms of social engineering.

I think that in a pathed context, we can restrict this further and make those powerful capabilities unavailable. The header would look like this:

Permissions-Policy: accelerometer=(),ambient-light-sensor=(),attribution-reporting=(),autoplay=(),battery=(),
                    bluetooth=(),browsing-topics=(),camera=(),ch-device-memory=(),ch-downlink=(),
                    ch-dpr=(),ch-ect=(),ch-lang=(),ch-prefers-color-scheme=(),ch-rtt=(),ch-save-data=(),
                    ch-ua=(),ch-ua-arch=(),ch-ua-bitness=(),ch-ua-full=(),ch-ua-full-version=(),
                    ch-ua-full-version-list=(),ch-ua-mobile=(),ch-ua-model=(),ch-ua-platform=(),
                    ch-ua-platform-version=(),ch-ua-reduced=(),ch-ua-wow64=(),ch-viewport-height=(),
                    ch-viewport-width=(),ch-width=(),clipboard-read=(),clipboard-write=(),conversion-measurement=(),
                    cross-origin-isolated=(),direct-sockets=(),display-capture=(),document-domain=(),
                    encrypted-media=(),execution-while-not-rendered=(),execution-while-out-of-viewport=(),
                    federated-credentials=(),focus-without-user-activation=(),fullscreen=(),gamepad=(),
                    geolocation=(),gyroscope=(),hid=(),idle-detection=(),interest-cohort=(),
                    join-ad-interest-group=(),keyboard-map=(),local-fonts=(),magnetometer=(),microphone=(),
                    midi=(),navigation-override=(),otp-credentials=(),payment=(),picture-in-picture=(),
                    publickey-credentials-get=(),run-ad-auction=(),screen-wake-lock=(),serial=(),shared-autofill=(),
                    shared-storage=(),speaker-selection=(),storage-access-api=(),sync-script=(),sync-xhr=(),
                    trust-token-redemption=(),unload=(),usb=(),vertical-scroll=(),wake-lock=(),web-share=(),
                    window-placement=(),xr-spatial-tracking=()

So, errr, yeah, your eyes might be bleeding right now and I'm sorry about that. Also, that list grows all the time. It's not great. There are issues about making a blanket "remove anything that might be dangerous" mode but so far they haven't been accepted.

We could decide to keep some things allowed (like camera or sync XHR) if we're worried about breaking legit use cases. But at least this list (which is the most comprehensive I could find — I'm looking into whether there's a reliable way to get an up-to-date list) makes things pretty tight and safe, on top of CSP and clearing the data.

@lidel
Copy link
Member Author

lidel commented Feb 21, 2023

Pretty hardcore, but for sure will do the trick of forcing people to move to subdomain gateways.

I propose we do a test run: set Permissions-Policy, Clear-Site-Data and a strict Content-Security-Policy on ipfs.io first, in Nginx, and see if there are any screams from the distance.

If the sky does not fall, me and @hacdias can apply this to all path requests in go-libipfs/gateway library.

@darobin
Copy link
Collaborator

darobin commented Feb 22, 2023

In addition to Permissions-Policy, I think the following would be good:

Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' data: ; form-action 'self'; connect-src 'self' data: ; manifest-src 'none' ; object-src 'none' ; sandbox allow-forms allow-modals allow-scripts allow-top-navigation-by-user-activation
Clear-Site-Data: "cookies", "storage"
X-Content-Type-Options: nosniff
X-Frame-Options: sameorigin

Some quick notes:

  • I reviewed the options for Clear-Site-Data and agree with your original proposal.
  • For the CSP, I don't include blob: which means no file uploads (even locally). One thing that we could add (dynamically) would be the URL up to the CID inclusive (eg. https://ipfs.io/ipfs/someCID/) instead of 'self' for default/connect/form.
  • I didn't block navigate-to, I think linking to other sites should be ok (but I can change my mind).
  • I didn't block worker-src because I don't think that there's much left that a worker could do, but it's easy to add.
  • I don't think that we want CSP reporting, but it's easy enough to add.
  • I didn't include allow-same-origin in sandbox, that's pretty strict and might break things. What this does is that it puts the document in a weird origin of its own, all alone, and every request from that becomes cross-origin, which means that doing things that would require CORS when talking to another server now require CORS when talking to the same server, which is pretty neat. One issue is that it blocks font loading (because fonts require CORS) — maybe that's a problem? Alternatively, we could keep this strong and add Access-Control-Allow-Origin: this.site on requests that match fonts. I haven't found a way to have this sandboxing but not for fonts.
  • I believe that you already have nosniff, threw it in for completeness.
  • X-Frame-Options in case anyone is trying to inject this in an iframe elsewhere.

I did some very superficial testing on static content, and it works. If you want to play with it locally, run this with a path to a dir to serve from:

#!/usr/bin/env node

import process from 'process';
import express from 'express';
const app = express();

app.use((req, res, next) => {
  res.set({
    'Permissions-Policy': 'accelerometer=(),ambient-light-sensor=(),attribution-reporting=(),autoplay=(),battery=(),bluetooth=(),browsing-topics=(),camera=(),ch-device-memory=(),ch-downlink=(),ch-dpr=(),ch-ect=(),ch-lang=(),ch-prefers-color-scheme=(),ch-rtt=(),ch-save-data=(),ch-ua=(),ch-ua-arch=(),ch-ua-bitness=(),ch-ua-full=(),ch-ua-full-version=(),ch-ua-full-version-list=(),ch-ua-mobile=(),ch-ua-model=(),ch-ua-platform=(),ch-ua-platform-version=(),ch-ua-reduced=(),ch-ua-wow64=(),ch-viewport-height=(),ch-viewport-width=(),ch-width=(),clipboard-read=(),clipboard-write=(),conversion-measurement=(),cross-origin-isolated=(),direct-sockets=(),display-capture=(),document-domain=(),encrypted-media=(),execution-while-not-rendered=(),execution-while-out-of-viewport=(),federated-credentials=(),focus-without-user-activation=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),hid=(),idle-detection=(),interest-cohort=(),join-ad-interest-group=(),keyboard-map=(),local-fonts=(),magnetometer=(),microphone=(),midi=(),navigation-override=(),otp-credentials=(),payment=(),picture-in-picture=(),publickey-credentials-get=(),run-ad-auction=(),screen-wake-lock=(),serial=(),shared-autofill=(),shared-storage=(),speaker-selection=(),storage-access-api=(),sync-script=(),sync-xhr=(),trust-token-redemption=(),unload=(),usb=(),vertical-scroll=(),wake-lock=(),web-share=(),window-placement=(),xr-spatial-tracking=()',
    'Content-Security-Policy': `default-src 'self' 'unsafe-inline' 'unsafe-eval' data: ; form-action 'self'; connect-src 'self' data: ; manifest-src 'none' ; object-src 'none' ; sandbox allow-forms allow-modals allow-scripts allow-top-navigation-by-user-activation`,
    'X-Content-Type-Options': 'nosniff',
    'X-Frame-Options': 'sameorigin',
  });
  next();
});
app.use(express.static(process.argv[2]));
app.listen(8888, () => console.warn(`Listening on http://localhost:8888`));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dif/expert Extensive knowledge (implications, ramifications) required effort/weeks Estimated to take multiple weeks kind/question A question or request for support need/analysis Needs further analysis before proceeding P1 High: Likely tackled by core team if no one steps up status/in-progress In progress topic/origin Issues related to Origin-based security
Projects
No open projects
Status: 🥞 Todo
Development

No branches or pull requests

3 participants