FlowCrypt / flowcrypt-browser

FlowCrypt Browser extension for Chrome and Firefox
https://flowcrypt.com
Other
372 stars 46 forks source link

change S3 settings to allow all CORS #3026

Closed seisvelas closed 3 years ago

seisvelas commented 4 years ago

Steps to reproduce:

  1. Send yourself a message via encrypted contact page
  2. Open the message and attempt to open the attachment

Result:

Error downloading file - no internet.
retry

And if you check the console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://flowcrypt.s3.amazonaws.com/attachment/74b45d0f43841befe54e693d4e7dfb8ac2745a66.pgp. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

And indeed, the files on S3 really are served without any CORS header.

Here are some S3 docs about enabling CORS: https://docs.aws.amazon.com/AmazonS3/latest/user-guide/add-cors-configuration.html

seisvelas commented 4 years ago

Or, StackOverflow discussion that might be helpful: https://stackoverflow.com/questions/17533888/s3-access-control-allow-origin-header

Or if you're okay with me accessing S3, I can do it.

tomholub commented 4 years ago

We allow only origins of known extensions. For example, on (prod) Firefox I can download the attachments ok.

Was this a local browser you were testing on? What was the extension id? I could add it to the S3 config.

(S3 will I think read the host header to respond with a CORS header if it's one of the good ones, else it will send back no cors header)

seisvelas commented 3 years ago

Ref: https://mail.google.com/mail/u/human@flowcrypt.com/#inbox/FMfcgxwKjKqwwMxfnWvjHwtsKfkHMhQc

My origin is moz-extension://7de1b3a0-9852-49de-ae57-8bef77b67cb7

I just removed and re-added the extension to Firefox and tried again - I get the same problem.

Now my origin is moz-extension://eb56e10a-70b2-4a2a-9bc8-662d1e890489

tomholub commented 3 years ago

The prod Firefox is moz-extension://39553fca-76d4-4791-bf00-b4dfede6fd45. Can you reproduce this on the prod?

seisvelas commented 3 years ago

I just installed fresh from the link on flowcrypt.com for Firefox, my origin is moz-extension://e0a5c2fc-950d-4492-8994-0dc5e0fcc885 and I'm getting this error.

Here is my request:

GET /attachment/d78d87f191052d54fa58eafb49efe22e07b9303e.pgp HTTP/1.1
Host: flowcrypt.s3.amazonaws.com
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Origin: moz-extension://e0a5c2fc-950d-4492-8994-0dc5e0fcc885
Connection: keep-alive
Range: bytes=34404-
If-Range: "8b4c7b5f81e3f156c1fd011e294f6a7b"

and the response:

HTTP/1.1 200 OK
x-amz-id-2: 2OCnBgxSr8YJwkuRg+bxwvRXQEp7lBzuRRECZGCEl291p6Z9CeuYqHjPnYv7we7Ka1VXgR3H8Lk=
x-amz-request-id: 167AC324FF4B1D2F
Date: Tue, 08 Dec 2020 00:19:03 GMT
Last-Modified: Mon, 07 Dec 2020 14:48:51 GMT
ETag: "8b4c7b5f81e3f156c1fd011e294f6a7b"
x-amz-server-side-encryption: AES256
Accept-Ranges: bytes
Content-Type: application/octet-stream
Content-Length: 226915
Server: AmazonS3

The error in my console:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://flowcrypt.s3.amazonaws.com/attachment/d78d87f191052d54fa58eafb49efe22e07b9303e.pgp. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Something we could perhaps improve is the error message as displayed to the user: "Error downloading file - no internet.". When that error is going to occur, we could check to see if it's a CORS issue and adjust the error message accordingly.

seisvelas commented 3 years ago

For context, I'm trying to open the attachment in this support email: https://mail.google.com/mail/u/human@flowcrypt.com/#inbox/FMfcgxwKjnXXjhVxfZmwmqJsMLXmzRJB

tomholub commented 3 years ago

Thank you for debugging this.

For example I can open that attachment just fine on Firefox:

image

I can see the origins are different. How come your origin is different from mine, if you just got it from Flowcrypt.com? Interesting. I'll try to re-download firefox in a separate profile.

tomholub commented 3 years ago

I just re-downloaded it myself and have moz-extension://4ed7f644-c3b5-4bf1-983f-2c8718f52222 ...

There surely is a mechanism to keep a stable extension id. Can you please take a look at what we have to do? We are using the addons.mozilla.com self-publish mechanism, where I'm having Mozilla sign each release, but then we are self-hosting a json file at https://flowcrypt.com/api/update/firefox the individual xpi fles.

seisvelas commented 3 years ago

There surely is a mechanism to keep a stable extension id.

Unfortunately, this appears not to be the case. Consider the following,

The internal UUID is deliberately created per installation of an extension, to avoid fingerprinting, you can see a longer discussion at https://bugzil.la/1372288

These IDs currently are unique per installation of an extension, but there is a discussion about this happening over at https://bugzilla.mozilla.org/show_bug.cgi?id=1271663 211

Since this extension ID in webextensions, is unique per user (https://bugzilla.mozilla.org/show_bug.cgi?id=1372288), it gives the possibility of fingerprinting the user on the server side based on the Origin header.

The Internal UUID displayed after moz-extension:// is particular to your Firefox.


Firefox's unfortunate approach to extension uuid assignment will probably be fixed eventually to work more like Chrome, based on discussions in the bug tracker, because it can be abused for tracking users by fingerprinting the unique origin header sent by their extension.

But that's not something we can wait on - the last comment from the dev in the bug tracker for this issue was 7 months ago saying they won't be fixing it soon.

tomholub commented 3 years ago

I see, it's a feature. Interesting. What's your thoughts on allowing S3 CORS * security wise?

seisvelas commented 3 years ago

What's your thoughts on allowing S3 CORS * security wise?

I'm not a fan, but the URL's with encrypted profile attachments are publicly accessible anyway (as long as you know the URL). I don't think an attacker could do much with this, but I'm learning all I can about CORS vulnerabilities in case I'm missing something (PortSwigger Academy has very thorough CORS vulnerability labs that are helping a lot).

With our current setup, though, we can't set Access-Control-Allow-Origin: * anyway, because browsers don't let you have both Access-Control-Allow-Origin: * and Access-Control-Allow-Credentials: true set simultaneously. The usual workaround is to just serve a CORS header that matches the Origin from the request (I'm sure AWS makes this easy to do, but if you need help I can set it up myself first on AWS free trial, then give you detailed instructions).

The GET request doesn't really need Access-Control-Allow-Credentials: true anyway. So maybe we could set POST requests to only allow the origin flowcrypt.com with Access-Control-Allow-Credentials: true (from the backend), and the GET requests could allow all origins but omit Access-Control-Allow-Credentials.

Let me know if you want any guidance for doing all of this on AWS :) In the meantime I'm going to look into more CORS vulnerabilities. I really don't want to suggest you do something unless I understand it very well. But so far I think we should be totally fine.

seisvelas commented 3 years ago

Almost all CORS attacks rely on Access-Control-Allow-Credentials: true, so if we could remove that for GET requests, allowing all origins for GET would be fine. And for POST, I think the only needed origin is flowcrypt.com, since that gets called from our backend. So that should solve any issue I can think of (but like I said, I'm still looking into all kinds of CORS attacks, so I'll update this late tonight after I study a ton and feel more confident

tomholub commented 3 years ago

I think browser extension posts to S3 directly, after getting authorization form from backend

On Sat, 12 Dec 2020, 03:01 Alex Vazquez, notifications@github.com wrote:

Almost all CORS attacks rely on Access-Control-Allow-Credentials: true, so if we could remove that for GET requests, allowing all origins for GET would be fine. And for POST, I think the only needed origin is flowcrypt.com, since that gets called from our backend. So that should solve any issue I can think of (but like I said, I'm still looking into all kinds of CORS attacks, so I'll update this late tonight after I study a ton and feel more confident

— You are receiving this because you modified the open/close state. Reply to this email directly, view it on GitHub https://github.com/FlowCrypt/flowcrypt-browser/issues/3026#issuecomment-743640053, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABQDZENAF7LTNRUQOALACX3SULFIFANCNFSM4SRMLBQQ .

seisvelas commented 3 years ago

Discussion on Keybase:

onirony Sorry to message you about this here, but I am a bit confused. So, I was thinking of profile messages, which are uploaded from the backend But for normal attachments, they don't even need S3, right? So when does the extension upload to S3? tomjh try a password protected message with attachments, and see the network tab onirony It calls api/message/token to get the auth stuff, then api/message/upload to host it, but no POST to S3 for me tomjh Maybe this changed. I'll have to take a look

So for now we're waiting to look into if the browser really does post directly to S3 anywhere.

tomholub commented 3 years ago

Indeed password-protected messages these days go from user to backend to S3.

Therefore POST is always from backend.

Therefore we could do Access-Control-Allow-Origin: * on GET, and Access-Control-Allow-Origin: flowcrypt.com on POST. Did it get it correctly?

seisvelas commented 3 years ago

Therefore we could do Access-Control-Allow-Origin: * on GET, and Access-Control-Allow-Origin: flowcrypt.com on POST. Did it get it correctly?

Yep, correct - we should be able to go ahead and make that change! Let me know when it's done and I'll test it on Firefox and (hopefully) close this issue.

Thanks for verifying that POSTs only come from the backend!

seisvelas commented 3 years ago

@tomholub I'm getting a new, different error when opening attachments sent via the encrypted contact page:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://flowcrypt.s3.amazonaws.com/attachment/2fe6179da6ed675fc0c21fe3416e0f5a801ffcbd.pgp. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Looking at the response, it appears the header is not being sent at all.

Here is the error from a user perspective, as always:

Screen Shot 2021-03-09 at 21 04 47

Did you change CORS settings? If so, I believe we may have inadvertently excluded CORS headers entirely on GET requests, rather than allowing all origins (which was our intent).

seisvelas commented 3 years ago

So there appear to be two separate bugs now.

In Firefox, as noted in my previous comment, CORS headers aren't received at all:

Screen Shot 2021-04-02 at 17 03 23

And on Chrome, the headers come in just fine but the preview fails for other reasons:

Screen Shot 2021-04-02 at 17 13 22

Here are the good headers, which are not the problem:

Screen Shot 2021-04-02 at 17 15 57

But here's the actual HTML for the image:

<div id="attachment-preview-container">
    <img src="blob:chrome-extension://bnjglocicdkmhmoohhfkfkbbkejdhdgc/eafb680e-46a7-4a65-b5ed-b46f25ee2404" class="attachment-preview-img" alt="fc.jpeg">
</div>

So the img source is obviously bad. I'm not what's going on there. We must have broken how profile message attachments are decrypted and loaded into the preview blob, and since we probably don't have a test for that we didn't notice.

At least, that's my hypothesis, and if it's true we need to do two things:

  1. Fix CORS for Firefox extension on AWS
  2. Troubleshoot & fix profile message attachment preview in general
tomholub commented 3 years ago

updated on both test and prod S3 bucket