Closed Bug 1218110 Opened 8 years ago Closed 8 years ago

Cross-origin restriction bypass using Workers.

Categories

(Core :: DOM: Workers, defect)

41 Branch
defect
Not set
normal

Tracking

()

RESOLVED DUPLICATE of bug 1160890

People

(Reporter: qab, Unassigned)

Details

(Keywords: sec-high)

Attachments

(2 files)

User Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:41.0) Gecko/20100101 Firefox/41.0
Build ID: 20151014143721

Steps to reproduce:


The importScripts(https://developer.mozilla.org/en-US/docs/Web/API/WorkerGlobalScope/importScripts) function has absolutely no restrictions 

when it comes to executing javascript from cross-origin locations.

Example 1:
 x=new Worker(URL.createObjectURL(new Blob(['importScripts("https://www.facebook.com/")'])));





Actual results:

Execution will lead to the error SyntaxError: expected expression, got '<'


Expected results:

Block attempt to importScripts due to Cross-Origin restrictions.
Attached file sopbypass.html
PoC to retrieve sensitive data using this bug in conjunction with a data leak in firefox errors(bubbling?) that exposes the worker (or potential worker) location. Since some websites force redirection and add sensitive information to the end of the url (session id, CSRF token..etc) we can use this flaw to retrieve sensitive information. As with this PoC, it will retrieve your facebook name.
Note: The facebook name getter PoC sometimes will return 'profile.php' as the name. This is because im retrieving from 'https://m.facebook.com/me'. If we replace it with 'https://www.facebook.com/me' instead, it should always work. (assuming youre logged on)
Group: firefox-core-security → core-security
Component: Untriaged → DOM: Workers
Product: Firefox → Core
Attached file sopbypass2.html
Here is a better version of the PoC.
Should I make a separate report for the Worker location leak in the error object?
baku/ckerschb: this looks like it's related to, or maybe a regression of, bug 949706... can either of you investigate/advise, also wrt:

(In reply to Abdulrahman Alqabandi from comment #4)
> Should I make a separate report for the Worker location leak in the error
> object?
Flags: needinfo?(mozilla)
Flags: needinfo?(amarchesini)
(In reply to :Gijs Kruitbosch (at OSCON, limited availability) from comment #5)
> baku/ckerschb: this looks like it's related to, or maybe a regression of,
> bug 949706... can either of you investigate/advise, also wrt:

Hm, unfortunately I don't think it's a regression of bug 949706. The reason CSP (and also MixedContent) are consulted correctly for redirects is, because those two security features use their own ::AsyncOnChannelRedirect() implementation and hence get consulted after redirects. As long as we haven't converted all callsites to use AsyncOpen2() we are in a somewhat inconsistent state where the loadInfo on the channel is used to perform CSP and Mixed content checks after redirects, but the same info is not used when performing the initial security checks.

Anyway, I would assume that Bug 1211967, where we start to use asyncOpen2() within dom/workers/scriptLoader (or also Bug 1206955), should fix the problem described here and should apply the right same origin restriction.

CC'ing Jonas and Boris to confirm.
Flags: needinfo?(mozilla) → needinfo?(jonas)
importScripts doesn't have any same-origin restrictions, just like <script> doesn't have any same-origin restrictions, and importScripts has the same behavior in terms of executing the script in the global of the worker and in the worker's origin.  Why do you think there should be same-origin restrictions here?

For reference, the spec for importScripts is at https://html.spec.whatwg.org/multipage/workers.html#importing-scripts-and-libraries which invokes https://html.spec.whatwg.org/multipage/workers.html#import-scripts-into-worker-global-scope none of which does any same-origin checks.

Contrast this with, for example, the Worker constructor, which is defined at https://html.spec.whatwg.org/multipage/workers.html#dom-worker and does perform a same-origin check in step 5.
Flags: needinfo?(qab)
(In reply to Boris Zbarsky [:bz] from comment #7)
> importScripts doesn't have any same-origin restrictions, just like <script>
> doesn't have any same-origin restrictions, and importScripts has the same
> behavior in terms of executing the script in the global of the worker and in
> the worker's origin.  Why do you think there should be same-origin
> restrictions here?
> 
> For reference, the spec for importScripts is at
> https://html.spec.whatwg.org/multipage/workers.html#importing-scripts-and-
> libraries which invokes
> https://html.spec.whatwg.org/multipage/workers.html#import-scripts-into-
> worker-global-scope none of which does any same-origin checks.
> 
> Contrast this with, for example, the Worker constructor, which is defined at
> https://html.spec.whatwg.org/multipage/workers.html#dom-worker and does
> perform a same-origin check in step 5.

This is what I thought at first, but looking at the first testcase, I think the problem seems to be that you can listen for errors on cross-origin loads, and that errors indicate post-redirect filenames. I'm assuming (but haven't checked) that at least one of those is not true for normal script loads. Does that make more sense?
Flags: needinfo?(bzbarsky)
> you can listen for errors on cross-origin loads

Ah, that information was in comment 1, not comment 0.  That's fixed in bug 1160890.  The expected results in comment 0 are just wrong; the correct expected result is that importScripts works fine but exceptions are muted.
Status: UNCONFIRMED → RESOLVED
Closed: 8 years ago
Flags: needinfo?(bzbarsky)
Resolution: --- → DUPLICATE
(In reply to Boris Zbarsky [:bz] from comment #7)
> importScripts doesn't have any same-origin restrictions, just like <script>
> doesn't have any same-origin restrictions, and importScripts has the same
> behavior in terms of executing the script in the global of the worker and in
> the worker's origin.  Why do you think there should be same-origin
> restrictions here?
> 
> For reference, the spec for importScripts is at
> https://html.spec.whatwg.org/multipage/workers.html#importing-scripts-and-
> libraries which invokes
> https://html.spec.whatwg.org/multipage/workers.html#import-scripts-into-
> worker-global-scope none of which does any same-origin checks.
> 
> Contrast this with, for example, the Worker constructor, which is defined at
> https://html.spec.whatwg.org/multipage/workers.html#dom-worker and does
> perform a same-origin check in step 5.

The request from importScripts() does not contain the 'referer' header, nor a 'origin' header as well. Given that the request is fully credentialed (by standard) it should at least contain those headers, or even better, blocked by a security measure (that should exist) which blocks these types of cross-origin requests.
Flags: needinfo?(qab)
> The request from importScripts() does not contain the 'referer' header, nor a 'origin'
> header as well. 

Most requests don't contain an 'origin' header.  The exception are CORS requests.  There has been some thought about adding an 'origin' header to other requests too, but that's not importScripts specific.

These requests should probably have a 'referer' header.  I filed bug 1218474 on that.

> or even better, blocked by a security measure

You mean one a page can opt into?  I would expect content security policy to work for this... but in your case the page is the attacker, so wouldn't opt into it anyway.
Put another way, the intent of the spec is that there is nothing you can do with importScripts that you can't do just as well with a <script> tag, in terms of attacking the target of the load.
Flags: sec-bounty+
Flags: sec-bounty+ → sec-bounty-
This is not what the spec says. importScripts is like <script src=something>: https://html.spec.whatwg.org/multipage/workers.html#dom-workerglobalscope-importscripts
Flags: needinfo?(jonas)
Flags: needinfo?(amarchesini)
(In reply to Boris Zbarsky [:bz] from comment #12)
> Put another way, the intent of the spec is that there is nothing you can do
> with importScripts that you can't do just as well with a <script> tag, in
> terms of attacking the target of the load.

I actually completely missed that the <script> tags behaved in the same manner as importScripts(). Could the error data leak also work with a <script> tag?
Well, in theory, if someone screws up error muting for <script>.
> The request from importScripts() does not contain the 'referer' header, nor
> a 'origin' header as well. Given that the request is fully credentialed (by

This is wrong. importScripts requests and main worker script requests do contain referer header.
(In reply to Andrea Marchesini (:baku) from comment #16)
> > The request from importScripts() does not contain the 'referer' header, nor
> > a 'origin' header as well. Given that the request is fully credentialed (by
> 
> This is wrong. importScripts requests and main worker script requests do
> contain referer header.

Strange, Im pretty sure it had no referer nor origin when I tested at the time. (perhaps it was fixed in 42?)
The code that sets referrer dates back to bug 1168933, the header is sent starting with version 41.
(In reply to Boris Zbarsky [:bz] from comment #18)
> The code that sets referrer dates back to bug 1168933, the header is sent
> starting with version 41.

I guess I made a mistake, my apologies.
Group: core-security → core-security-release
Group: core-security-release
Keywords: sec-high
You need to log in before you can comment on or make changes to this bug.