Why have Origin and Referer headers when Referer has enough information? - http

If the Referer header has the Origin in it anyway, what is the point of having both?
If the server receiving an HTTP request wants to know the Origin, it can just look at the domain in the Referer header.
I understand that the Referer header is not sent if it's an HTTPS to HTTP request (and many other scenarios), but why didn't they design it so that instead of removing it, it was still sent, but it only had the domain name (what the Origin header would have)?

Citing from here https://security.stackexchange.com/questions/158045/is-checking-the-referer-and-origin-headers-enough-to-prevent-csrf-provided-that
In order to preserve privacy, any browser request can decide to omit
the Referer header. So it is probably best to only check the Origin
header. (In case you want to allow for users to preserve their
privacy)
The Origin header is null in some cases. Note that all of these
requests are GET requests, which means they should not have any side
effects.

Related

CORS redirect from http to https

Just found out that when you return 301 Redirect status from your server to a CORS request, the browser set the subsequent 'Origin' header to 'null'. Apparently this is for privacy reason, but I'm only referring from http to https in my nginx server! Oh well.. what can you do.
On my nginx config for https, I am checking $http_origin before adding my CORS headers. Since the browser set the damn Origin header to 'null', the header didn't got added to the response.
Is there anyway around this problem or I'm forced to just make sure my Origin client sends only https requests?
Hope the question is not too broad.
Protocol scheme is one of the elements that define Origin, so http://x.com is a different origin from https://x.com
In CORS, after redirect, the browser sends Origin: null, this is by design.
To overcome this you have two options:
Allow Origin: null but please make sure you understand the implications as it actually means you're allowing all origins.
Add to the redirect url some proof that this is a valid url that came from your server. Some secret that only the server can generate. When Origin: null is present, allow it only if this is a valid secret.

When should I really set "Access-Control-Allow-Credentials" to "true" in my response headers?

MDN says, when the credentials like cookies, authorisation header or TLS client certificates has to be exchanged between sites Access-Control-Allow-Crendentials has to be set to true.
Consider two sites A - https://example1.xyz.com and another one is B- https://example2.xyz.com. Now I have to make a http Get request from A to B. When I request B from A I am getting,
"No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://example1.xyz.com' is therefore not allowed
access."
So, I'm adding the following response headers in B
response.setHeader("Access-Control-Allow-Origin", request.getHeader("origin"));
This resolves the same origin error and I'm able to request to B. When and why should I set
response.setHeader("Access-Control-Allow-Credentials", "true");
When I googled to resolve this same-origin error, most of them recommended using both headers. I'm not clear about using the second one Access-Control-Allow-Credentials.
When should I use both?
Why should I set Access-Control-Allow-Origin to origin obtained from request header rather than wildcard *?
Please quote me an example to understand it better.
Allow-Credentials would be needed if you want the request to also be able to send cookies. If you needed to authorize the incoming request, based off a session ID cookie would be a common reason.
Setting a wildcard allows any site to make requests to your endpoint. Setting allow to origin is common if the request matches a whitelist you've defined. Some browsers will cache the allow response, and if you requested the same content from another domain as well, this could cause the request to be denied.
Setting Access-Control-Allow-Credentials: true actually has two effects:
Causes the browser to actually allow your frontend JavaScript code to access the response if credentials are included
Causes any Set-Cookie response header to actually have the effect of setting a cookie (the Set-Cookie response header is otherwise ignored)
Those effects combine with the effect that setting XMLHttpRequest.withCredentials or credentials: 'include' (Fetch API) have of causing credentials (HTTP cookies, TLS client certificates, and authentication entries) to actually be included as part of the request.
https://fetch.spec.whatwg.org/#example-cors-with-credentials has a good example.
Why should I set Access-Control-Allow-Origin to origin obtained from request header rather than wildcard *?
You shouldn’t unless you’re very certain what you’re doing.
It’s actually safe to do if:
The resource for which you’re setting the response headers that way is a public site or API endpoint intended to be accessible by everyone, and
You’re just not setting cookies that could enable an attacker to get access to sensitive information or confidential data.
For example, if your server code is just setting cookies just for the purpose of saving application state or session state as a convenience to your users, then there’s no risk in taking the value of the Origin request header and reflecting/echoing it back in the Access-Control-Allow-Origin value while also sending the Access-Control-Allow-Credentials: true response header.
On the other hand, if the cookies you’re setting expose sensitive information or confidential data, then unless you’re really certain you have things otherwise locked down (somehow…) you really want to avoid reflecting the Origin back in the Access-Control-Allow-Origin value (without checking it on the server side) while also sending Access-Control-Allow-Credentials: true.
If you do that, you’re potentially exposing sensitive information or confidential data in way that could allow malicious attackers to get to it. For an explanation of the risks, read the following:
https://web-in-security.blogspot.jp/2017/07/cors-misconfigurations-on-large-scale.html
http://blog.portswigger.net/2016/10/exploiting-cors-misconfigurations-for.html
And if the resource you’re sending the CORS headers for is not a public site or API endpoint intended to be accessible by everyone but is instead inside an intranet or otherwise behind some IP-address-restricted firewall, then you definitely really want to avoid combining Access-Control-Allow-Origin-reflects-Origin and Access-Control-Allow-Credentials: true. (In the intranet case you almost always want to only be allowing specific hardcoded/whitelisted origins.)

No custom headers when setFullResponse(true)

I'm using Restangular. I would like to get full response so I set
Restangular.setFullResponse(true);
but then I discovered that my custom headers does not work. Documentation for setFullResponse() method says:
in order for Restangular to access custom HTTP headers, your server must respond having the Access-Control-Expose-Headers: set.
I would like to send my custom headers but I don't want to change server settings. Is it possible?
If I leave default settings i.e.setFullResponse(false) there is no issue with custom headers. Is there another solution except changing server settings?
The sentence you cite from the setFullResponse() docs is about what headers from the response your Restangular app will be able to access. And what that is saying is, it’s not possible to access most of the headers from the response unless the server’s already configured to send the right response-header names in the Access-Control-Expose-Headers header.
Without the server setting any value for that header, the only response headers that browsers will let you access from client-side JavaScript in your web app are the Cache-Control,
Content-Language,
Content-Type,
Expires,
Last-Modified
&
Pragma response headers.
See https://fetch.spec.whatwg.org/#cors-safelisted-response-header-name for the spec on that.
I would like to send my custom headers but I don't want to change server settings. Is it possible?
If you mean you want to send custom headers in a request from your client-side Restangular code to the server, please provide more details about exactly which custom headers you want to send.
There too though, there’s another CORS header your server must send in the response: the Access-Control-Allow-Headers response header. If the server isn’t configured to send that with the right header names listed, then your request will fail. The reason in that case is, you will hit https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests.

In the respective of security, is it meaningful to allow CORS for specific domains?

We can set and allow cross-origin-resource-sharing for
All domains , Specific domains and Not allow for any domains
But I wonder allowing CORS for specific domains meaningful.
If a hacker knows the domains that server allows. (e.g www.facebook.com)
Hacker can fake the origin header in the request as www.facebook.com
Thus, in the perspective of security. I think only Allow all domains and Not allow for any domains are meaningful. Since it is very easy to fake the origin of the requester
Am I right??
Browsers are where CORS restrictions are enforced. And browsers know the real origin a script runs in. That’s how they work. If they didn’t, there would be zero security on the Web.
So browsers do CORS checks against what they know to be the real origin of the JavaScript code that’s making an XHR or fetch() request—not against the value of the Origin header.
And browsers are what set the Origin request header and send it over the network to begin with. Browsers set the Origin value based on what they know to be the real origin, and not for their own use—because they already know what the origin is and that value is what they use internally.
So even if you manage to change an Origin header a browser sends over the network, that won’t matter to the browser—it’s going to ignore that value and continue checking against the real origin.
More details
As far as CORS goes, servers just send back documents, with an Access-Control-Allow-Origin header and other CORS headers, to any client that requests them.
Consider if you use curl or something to request a document from a server: The server doesn’t check the Origin header and refuse to send the document if the requesting origin doesn’t match the Access-Control-Allow-Origin header. The server sends the response regardless.
And as far as clients go, curl and non-browser tools don’t have the concept of an origin to begin with and so don’t usually send any Origin header to begin with. You can make curl send one—with any value you want—but it’s pointless because servers don’t care what the value is.
And curl, etc., don’t check the value of the Access-Control-Allow-Origin response header the server sends, and refuse to get a document if the request’s Origin header doesn’t match the Access-Control-Allow-Origin header in the server response. They just get the document.
But browsers are different. Browser engines are really the only clients that have the notion of an origin to begin with, and that know the actual origin a Web application’s JavaScript is running in.
And unlike curl, etc., browsers will not let your script get a document if the XHR or fetch() call requesting it is from an origin not allowed in the server’s Access-Control-Allow-Origin header.
And again, the way browsers determine what the origin is by already knowing what the origin is, not based on the value of whatever Origin request header might end up getting sent in the request.

CORS - why is Access-control-allow-origin header necessary?

Premise:
When an site (http://example.com) tries to make a cross-origin request, the browser will send an HTTP request to the cross-origin server (http://other-server.com) with the header Origin: http://example.com. If the server at http://other-server.com approves http://example.com as a valid origin, then it will 1) Respond without error AND 2) set the response header to Access-control-allow-origin: http://example.com
My question is - why is it necessary to set the Access-control-allow-origin header in the response? Doesn't responding without error already acknowledge that the server (http://other-server.com) is allowing the cross-origin request?
This extra layer of acknowledgement gives servers a lot of flexibility over how they support CORS. For example:
1) A server has a lot of choices when setting the Access-Control-Allow-Origin header. It can use the * value to allow all clients, or it can limit the scope of clients by using the actual value of the origin (e.g. http://example.com). If a server does support CORS, but not for all origins, it could respond without error, but the Access-Control-Allow-Origin could be set to http://notyourorigin.com.
2) CORS allows even more flexibility via the Access-Control-Allow-Methods and Access-Control-Allow-Headers preflight response headers. These headers go beyond the simple binary success/error HTTP status, and provide more nuanced information about what is and is not supported in the server.
As the examples above point out, an error response without any context can be very confusing to the user. If you make a CORS request, and all you get back is an error response, you have no idea why that request failed. Are you doing the request wrong? Does the server support CORS at all? This can be very difficult to figure out without any accompanying information. The Access-Control-* gives more context to the user so they can effectively debug their CORS requests.

Resources