privacycg / proposals

New proposals in the Privacy Community Group
https://privacycg.github.io
122 stars 5 forks source link

Storage Access Headers #45

Open cfredric opened 7 months ago

cfredric commented 7 months ago

In the current Storage Access API specification, sites must explicitly opt into accessing their unpartitioned cookies. This explicit requirement is an intentional protection against CSRF, so that embedded iframes can choose whether they want to access unpartitioned cookies or not. However, there's currently only one way to opt into accessing unpartitioned cookies: by calling a JavaScript API. This effectively means that only embedded iframes can opt in, and they have to execute some JavaScript before being allowed to access cookies - even if the user has already granted the relevant permission. This causes unnecessary network traffic and resource loads/reloads.

At TPAC, I presented some slides (see slides 7-12) on ideas for new ways to "opt in" or "activate" an existing permission through the Storage Access API. In particular, the use of an HTTP response header instead of requiring a invocation of the JavaScript API. This generally got positive feedback (IMO) and other browser vendors seemed interested in exploring the ideas, in particular suggesting a complementary request header.

Explainer: https://github.com/cfredric/storage-access-headers

I'd appreciate any additional feedback, comments, concerns, etc. Thank you!

johannhof commented 7 months ago

CC @bvandersloot-mozilla @annevk

johnwilander commented 6 months ago

Following up on the PrivacyCG call we just had. I was asked to flesh out the scenario I tried to sketch.

I think browsers who want to enforce 1) per-page access to unpartitioned cookies, 2) with user activation will be under pressure to relax that if developers do this:

  1. The user is on news.example/startPage.
  2. An iframe from thirdParty.example on news.example/startPage gets a tap and requests storage access.
  3. Storage access is granted, either promptless because the user has opted in previously or with a prompt.
  4. The iframe from thirdParty.example signals to the top frame that it now has storage access.
  5. The top frame navigates to news.example/nextPage presenting the news or whatnot.
  6. Subresources from thirdParty.example on news.example/nextPage send the storage access HTTP response header because they "know" that news.example will only ever navigate the user to news.example/nextPage after storage access has been granted to thirdParty.example.

Per-page storage access with user activation will not work in the above case. Browser who prefer that as their privacy boundary will be pressured to either quirk all such websites or relax their storage access policy.

bvandersloot-mozilla commented 6 months ago

@johnwilander: We talked a bit about the privacy benefits of per-page access to unpartitioned cookies in the meeting- I wanted to follow up. You said that we shouldn't presume collaboration between first and third parties when setting our threat model, and I still agree.

However I don't think a third party requires collaboration to link their partitioned and unpartitioned storages permanently after a single grant. Here is the attack I'm thinking of:

  1. The user is on news.example/startPage.
  2. An iframe from thirdParty.example on news.example/startPage is loaded.
  3. The iframe Fetches a cross-site resource from an origin under their control thirdPartyOther.example/cookie-sync-1. This sets the partitioned cookie for thirdPartyOther.example, and renders it accessible to the frame's Javascript.
  4. The iframe gets a tap and requests storage access.
  5. Storage access is granted with a user prompt.
  6. The iframe on thirdParty.example POSTs their unpartitioned cookie string and partitioned cookie set in step 3 to a cross-site resource under their control thirdPartyOther.example/cookie-sync-2.
  7. On a subsequent page load on news.example, an iframe from thirdParty.example is loaded partitioned but fetches thirdPartyOther.example/cookie-sync-3, which can now respond with the unpartitioned cookie string that was POSTed with the same partitioned cookie from step 6.

I came up with this using partitioned cookies, but you can substitute Fetch request/response bodies and Storage where needed.

johnwilander commented 6 months ago

@johnwilander: We talked a bit about the privacy benefits of per-page access to unpartitioned cookies in the meeting- I wanted to follow up. You said that we shouldn't presume collaboration between first and third parties when setting our threat model, and I still agree.

However I don't think a third party requires collaboration to link their partitioned and unpartitioned storages permanently after a single grant. Here is the attack I'm thinking of:

  1. The user is on news.example/startPage.
  2. An iframe from thirdParty.example on news.example/startPage is loaded.
  3. The iframe Fetches a cross-site resource from an origin under their control thirdPartyOther.example/cookie-sync-1. This sets the partitioned cookie for thirdPartyOther.example, and renders it accessible to the frame's Javascript.
  4. The iframe gets a tap and requests storage access.
  5. Storage access is granted with a user prompt.
  6. The iframe on thirdParty.example POSTs their unpartitioned cookie string and partitioned cookie set in step 3 to a cross-site resource under their control thirdPartyOther.example/cookie-sync-2.
  7. On a subsequent page load on news.example, an iframe from thirdParty.example is loaded partitioned but fetches thirdPartyOther.example/cookie-sync-3, which can now respond with the unpartitioned cookie string that was POSTed with the same partitioned cookie from step 6.

I came up with this using partitioned cookies, but you can substitute Fetch request/response bodies and Storage where needed.

Yup, syncing partitioned storage with unpartitioned storage is a threat indeed. That’s in part why WebKit makes all partitioned storage ephemeral which at least limits it to per-session. But I agree it points towards this response header opt-in not worsening things. I’ll have to think about it some more.

cfredric commented 6 months ago

Thanks Ben, that's a good illustration that the header doesn't regress any existing privacy properties.

IMO browsers should assume that the embedded site knows its unpartitioned state once permission has been granted, whether document.requestStorageAccess() is called again (with or without user activation) or not.

martinthomson commented 6 months ago

@cfredric, I just untagged this, but I don't know if we reached a satisfactory conclusion when it was last discussed. Do you want to talk about this again at our upcoming call?

cfredric commented 6 months ago

Thanks Martin, we'd love for chairs to consider accepting this proposal as a Privacy CG work item. Would you suggest another discussion on a call for that or do you think the multi-stakeholder interest and discussion in this thread is sufficient?

johannhof commented 2 weeks ago

@martinthomson @bvandersloot-mozilla friendly ping on this question. We're implementing this and would like to start requesting feedback / positions, so we'll need a group to incubate in. Would be good to understand if that's PCG, which would be our preference, or whether it needs to be another group.