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

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.

Related

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

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.

What is an HTTP server expected to do when it receives an "Origin: null" header? (CORS)

The definition of the Origin header says:
origin-or-null = origin / %s"null" ; case-sensitive
Is "null" to be managed like a domain name? In other words, can the server accept requests when "null" was used (at least in some circumstances) or is it considered like a fault all the time?
I've looked for an explanation in the Fetch Documentation but so far I've not found an answer to this specific question.
By sending an Origin: null header, a browser is indicating the request is from an opaque origin. That is, the browser is signaling to you as a server maintainer that the request wasn’t initiated in a typical way from an app actually running on the web and using an Ajax method or Fetch or XHR to call your server — so it’s probably not a use case which you actually intend your service to support.
So you generally don’t want to send the Access-Control-Allow-Origin response header when responding to Origin: null requests. In other words, you want browsers to block any frontend JavaScript code from access to the response you send back for such requests.
While the most-common case when browsers set the Origin header to null is probably when frontend code is being run from somebody’s local filesystem (from a file:// URL, instead of from a Web server) — there are a number of other cases where browsers also set the Origin header to null. For an exhaustive list, see https://stackoverflow.com/a/42242802/441757.
https://w3c.github.io/webappsec-cors-for-developers/#avoid-returning-access-control-allow-origin-null has an explanation of how you should look at such cases:
It may seem safe to return Access-Control-Allow-Origin: "null" , but the serialization of the Origin of any resource that uses a non-hierarchical scheme (such as data: or file:) and sandboxed documents is defined to be "null". Many User Agents will grant such documents access to a response with an Access-Control-Allow-Origin: "null" header, and any origin can create a hostile document with a "null" Origin. The "null" value for the ACAO header should therefore be avoided.
In other words, you may think it’d be useful to send back Access-Control-Allow-Origin for Origin: null requests if you intentionally want to allow responses from your server to be consumed in frontend JavaScript code running on somebody’s local filesystem (e.g., for somebody doing local testing). But by doing that, you’d not be allowing just the local-filesystem case but also all the other cases described in https://stackoverflow.com/a/42242802/441757. It’s all or nothing.

How does EnableCors restrict the origin access

I have created a WebAPI controller as below
[EnableCors("http://localhost:1234", "*", "*"]
public class DummyController : ApiController
{
public string GetDummy()
{
return "Iam not DUMMY";
}
}
When I hit the service using ajax from my application which is hosted on locahost:5678 It throws error since it is not allowed but when I hit the same API from restclient like PostMan it returns data.
Questions
1) CORS restricts only ajax requests and not the normal HTTP requests because I believe postman sends normal http requests.
2) How does EnableCors restrict to provided origins? Consider if I modify the origin and referrer params in the ajax request I can fish the values. What strategy does CORS use to identify the referrer URL.
As W3C states HttpReferrer can be easily modified, one should not depend on its value to authorize the access. If that is the case What does EnableCors checking in behind to authorize the origin.
I could just change my origin in ajax request also. Please help me with this Iam pretty much confused
CORS restricts only ajax requests and not the normal HTTP requests because I believe postman sends normal http requests.
Yes, specifically browsers restrict Ajax requests — that is, browsers by default don’t allow frontend JavaScript code to access responses from cross-origin requests made with XMLHttpRequest, the Fetch API, or with Ajax methods from JavaScript libraries.
Servers don’t themselves enforce any restrictions on cross-origin requests; instead, servers send responses to any clients that make requests to them, including postman — and including browsers.
Browsers themselves always get the responses that any other client would; but just because the browser gets a response doesn’t mean the browser will allow frontend JavaScript code to access that response. Browsers will only expose a response for a cross-origin request to frontend code if the response includes the Access-Control-Allow-Origin header.
How does EnableCors restrict to provided origins?
It doesn’t. When you CORS-enable a server, the only effect that has is to cause the server to send additional response headers, based on the values of particular request headers it receives — in particular, the Origin request header.
Consider if I modify the origin and referrer params in the ajax request I can fish the values. What strategy does CORS use to identify the referrer URL.
Servers don’t (and can’t) do any validation of the Origin value to confirm it hasn’t been spoofed or whatever. But the CORS protocol doesn’t require servers to do that — because all CORS enforcement is done by browsers.
As W3C states HttpReferrer can be easily modified, one should not depend on its value to authorize the access. If that is the case What does EnableCors checking in behind to authorize the origin.
I could just change my origin in ajax request also. Please help me with this Iam pretty much confused
Browsers know the real origin of any frontend code that sends a cross-origin request, and browsers do CORS checks against what they know to be the real origin of the request — and not against the value of the Origin header.
Browsers are what set the Origin request header and send it over the network to begin with; they 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 for a request, that won’t matter to the browser — it’s going to ignore that value and continue checking against the real origin.
cf. the answer at
In the respective of security, is it meaningful to allow CORS for specific domains?

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.)

Browser doesn't send FQDN in Origin header

In the context of CORS, is it possible to coerce the browser to always send the Origin header with an FQDN? The target service should see Origin: http://website.intranet.example.com/page.html instead of Origin: http://website/page.html.
As the example implies this is an intranet environment and the goal is to filter request origins by subdomain to allow any page hosted on a domain machine (*.intranet.example.com) to make cross-origin requests to the service which is also hosted in the same domain. The problem (if you will) is that intranet sites are commonly addressed as http://website/ with the remainder implied by the connection-specific DNS suffix: intranet.example.com set via domain policy.
The only workaround I can think of is to require all the 'origin' pages to force canonical URLs (i.e. redirect //foo to //foo.intranet.example.com) with the least side effect of "ugly URLs".
In the CORS context, rather than trying to get Origin values the same for the short and the fully qualified domain name, you could just focus on whether the server should allow the request to proceed or not whether either Origin value is present:
Assuming that to allow the cross-origin request, the responding server only needs to respond with a suitable Access-Control-Allow-Origin response header, you could respond with the wildcard value to say any incoming Origin is ok:
Access-Control-Allow-Origin: *
If your client requires a specific domain instead of the wildcard, you could have the webserver just echo back the value of the incoming Origin header if you choose to allow the request to proceed, regardless of what the Origin value says it is.
e.g. in Apache, use the SetEnvIf and Header modules to write an environment variable containing the origin value if that value matches a specific regex, then if that variable exists write the Access-Control-Allow-Origin response header with the environment variable's value:
SetEnvIf Origin "(.+)" origin_header_value=$1
Header set Access-Control-Allow-Origin "%{origin_header_value}e" env=origin_header_value
If you need more fine grain control over whether the webserver includes the Access-Control-Allow-Origin header in this manner, you can just set a more restrictive regex in the SetEnvIf command instead of using .+.

Resources