CORS and X-Frame-Options security

3,902 views
Skip to first unread message

Brian Clozel

unread,
Oct 7, 2014, 9:14:19 AM10/7/14
to soc...@googlegroups.com
Hi,

I'm a Spring Framework committer and I'm working on Spring's SockJS implementation with my colleagues; I had some questions to the group.

Looking at the protocol specification [1] and existing implementations [2], it seems that for CORS-related browser requests, the SockJS implementation:
* either sends a "Access-Control-Allow-Origin"="*" HTTP response header
* or sends a "Access-Control-Allow-Origin"="[request origin]" response header, echoing back the request's origin header value to the client

In both cases, SockJS allows requests from any domain, even if the request comes from a third party domain (i.e. has "evil.com" as an Origin, while the SockJS server application is hosted on "example.org").

My questions are:

1) Why are we always sending CORS headers?
2) In our SockJS protocol server implementation, we plan to *not* send an "Access-Control-Allow-Origin" response header to the client, thus enforcing a same origin policy as a default behavior. What do you think?
3) Without further configuration by the developer, isn't a "same origin policy" a sane default?
4) Protocol tests/specs and implementations is sending those CORS headers; is this part of the SockJS protocol required behavior? A convenient default configuration to make it work out of the box in a cross-domain context? Or just a test artifact for the protocol to be tested in various setups? I find this a bit misleading, if not a security issue.
5) In our implementation, we plan to allow developers to explitely configure other origins; those values will be sent in CORS headers. Do other implementations already do this? Is there some common pattern on this SockJS implementations should follow?


When using the iframe transport, the current SockJS protocol spec does not mention the X-Frame-Options not Content-Security-Policy HTTP headers; they are often used to prevent clickjacking issues.

Questions:

6) Should those headers be sent along iframe HTTP responses, defaulting to a same origin policy? Or not sending them is enough?
7) When explictely configuring other authorized origins, should those headers values be the same as configured CORS authorized origins (see question #5)?



Thanks,

--
Brian Clozel

Bryce Kahle

unread,
Oct 7, 2014, 4:36:43 PM10/7/14
to bcl...@pivotal.io, soc...@googlegroups.com
SockJS is WebSocket emulation via several different transports, so security restrictions should ideally not be based on the underlying transport. Having the security logic in one place regardless of transport will reduce the chance of bugs and/or inconsistencies.

Origin validation is tricky because in the case of WebSockets, CORS does not apply. Thus you would need different logic per transport based on what data is available and what is possible.

In response to some of your specific questions:

1) Is there a problem with sending CORS headers? 

2 & 3) I would argue the reverse. Sticking to a default of any origin policy, while still allowing tighter restrictions to be applied.

4) Cross-origin enabled does appear to be the default. I don’t think it is a strict requirement because it is definitely a per-deployment security decision. AFAIK there is nothing in the protocol that requires any origin.

5) Having recently taken over maintenance, and most of my focus thus far being the client-side library, I’m not super familiar with each server implementation. I don’t think this is bad approach to take assuming it is well documented. I would be happy to look over your proposal if you like.

6) We aren’t rendering content within the iframe, so I don’t think clickjacking is really an issue. It does appear that X-Frame-Options is obsolete [1] and frame-ancestors CSP is the modern way to do it. You would probably want to use both in tandem to get good browser coverage [2]. The only iframe security in use I’m aware of is having the server control where the SockJS library is loaded from [3].

7) Yes. I think they should be the same. The idea is the user isn’t aware of the underlying transport being utilized.






Bryce


--
You received this message because you are subscribed to the Google Groups "sockjs" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sockjs+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Bryce Kahle

unread,
Oct 7, 2014, 4:43:43 PM10/7/14
to bcl...@pivotal.io, soc...@googlegroups.com
One thing to keep in mind is that there is nothing requiring SockJS to be used from a browser client.


Bryce


On Tue, Oct 7, 2014 at 9:14 AM, Brian Clozel <bcl...@pivotal.io> wrote:

--

Brian Clozel

unread,
Oct 8, 2014, 9:06:21 AM10/8/14
to Bryce Kahle, soc...@googlegroups.com
Hi Bryce,

Thanks for your detailed answers.

I agree completely, "security restrictions should ideally not be based on the underlying transport".

1) 2) 3) I'm still not convinced about the same/any origin pocily default choice. Why should be choose a default policy that's the exact opposite of what browser chose in the first place? A great deal of applications use a single domain, so maybe this is the case to optimize for (and if developers want to allow multiple domains, then it should be done manually).
I do think that our current users aren't configuring CORS themselves, thinking that the default experience is secure for a "single domain" deployment. That is misleading.

4) The point I'm also trying to make here, it's not quite clear where those concerns belong; sockjs-protocol tests are somewhat the definition of the protocol itself, but CORS headers aren't flagged as "implementation details" or "not part of the protocol". Maybe some comments in the test suite could be useful to make that clear?

5) Thanks! I'll definitely send you some pointers once we've drafted our design

6) Good point

7) I guess the challenge here is to separate protocol requirements / general guidelines / implementation design - and provide a great experience for all SockJS implementations!

Thanks!

--
Brian Clozel

Chris Gamble

unread,
Oct 8, 2014, 4:46:32 PM10/8/14
to bcl...@pivotal.io, Bryce Kahle, soc...@googlegroups.com
Hey Brian,

Websockets don't follow SOP/CORS by default in browsers, so when SockJS undermines CORS for it's underlying transports it's actually following the browser's standard - not deviating from it. Furthermore, some of the transports used by SockJS, like JSONP, don't follow SOP/CORS and so even if CORS was enforced for the transports that provide it, other domains could still connect to your SockJS server. Therefore it'd be misleading to developers using SockJS to imply that a CORS policy offers any security benefit, and might actually lead to a less secure SockJS server as the developer might expect CORS to handle it all for them.

In general, I believe the approach of SockJS is "we'll set up the bi-directional communication, you're in charge of the rest". Authentication, origin validation, etc are all concerns above the protocol level. Perhaps if you're concerned about security for your end-users, you could provide middleware that makes that simple, that rests on top of your SockJS server implementation? That way you don't have to modify the protocol, but you can make it easy to validate someone came from your site, potentially by passing a nonce through the html page and back through the SockJS connection (similar to a CSRF token).

Cheers,

Chris Gamble
Reply all
Reply to author
Forward
0 new messages