I have a web application behind an OIDC reverse proxy -- in other words, when I visit this application I am redirected to my identity provider, I log in and my browser sets a cookie which is used on subsequent requests to prove that I have logged in.
This cookie has the HttpOnly flag set, which I understand to be best practice to prevent XSS vulnerabilities being exploited by a malicious website.
However, as expected, Javascript within my application does not have access to the login cookie, so in my browser's console I see requests back to the application (trying to update dynamic content through both HTTP requests and websocket connections) being redirected to my identity provider (and blocked by CORS policy) since they do not have access to the login cookie.
Does this mean that such an architecture cannot use Javascript to call back to the application?
Is it common to disable the HTTPOnly flag to allow Javascript to work in such a case?
My understanding is that Javascript from a malicious website at a different origin trying to access my application would be blocked by CORS anyway, so would keeping the HTTPOnly flag only help against attacks where the attacker managed to inject Javascript into my application?
Does this mean that such an architecture cannot used Javascript?
No. It means JS cannot read data from the cookie.
I see requests back to the application (trying to update dynamic content through both HTTP requests and websocket connections) being redirected to my identity provider (and blocked by CORS policy) since they do not have access to the login cookie.
The CORS policy should not block requests because cookies are missing.
If a cookie is missing then it is probably because you are (a) getting your origins mixed up and that origin doesn't have a cookie or (b) you didn't enable the credentials option for a cross-origin request.
Is it common to disable the HTTPOnly flag to allow Javascript to work?
No.
My understanding is that Javascript from a malicious website at a different origin trying to access my application would be blocked by CORS anyway, so would keeping the HTTPOnly flag only help against attacks where the attacker managed to inject Javascript into my application?
Yes. XSS attacks are so common that there are many tools to mitigate against them. This is one of them.
I have a web method that I want to call from my C# app and was provided with a Javascript example, showing how to call the method. I have established that running the Javascript from my desktop runs into CORS problems - i was able to run the sample when I put the javascript on the server and ran it from the same folder as the web method.
Will my C# app run into the same CORS issue? or will it be ok because only the browsers have the built in CORS security?
--Edit--
I've been using System.Net.Http.HttpClient and http://restsharp.org/
Am I correct in assuming that these two objects are wrappers around a web browser? and that they will have issues with CORS?
I really don't want to have to write Sockets code.
Due to security reasons browsers restrict cross-origin HTTP requests initiated from within scripts on the browser. For example, XMLHttpRequest follows the same-origin policy. That means a web application using XMLHttpRequest could only make HTTP requests to its own domain. This prevents application from being vulnerable to CSRF attacks. However, there are cases when applications need to access resources from different domain. This is when CORS comes into play to allow cross-domain requests.
Having said all that, your C# app should be able to call the WEB API without any CORS issues as long as it's a socket to socket communication (not via browser).
Some where in deep recess of my mind I remember browser related cors will always be blocked unless noted or changed like for example if you're in chrome and have the cors extension allow browser cors control, but on the server side, their is nothing preventing servers from interacting with one another.
but it depends on what is allowed on the headers
I'll try to produce some documentation that confirms that.
https://spring.io/understanding/CORS
The request includes an Origin header that indicates the origin of the client code.
The server will consider the request's Origin and either allow or disallow the request. If the server allows the request, then it will respond with the requested resource and an Access-Control-Allow-Origin header in the response. This header will indicate to the client which client origins will be allowed to access the resource. Assuming that the Access-Control-Allow-Origin header matches the request's Origin, the browser will allow the request.
On the other hand, if Access-Control-Allow-Origin is missing in the response or if it doesn't match the request's Origin, the browser will disallow the request.
So you can't make a request to another domain under the same origin policy. But does that apply to code you running inside the Chrome JS console with the page of that domain opened? And does that apply to a backend server app making a request to the other domain?
Question1: Chrome
When you run code inside Chrome JS console, you are running code in the context of a given page and you inherit the same security sandbox that the page has. All web pages are subject to CORS restrictions (cross origin resource sharing).
As a side note, cross origin request are allowed if the API you are calling explicitely allows them (which is implemented server side by setting some HTTP headers), or if you use another legacy cross origin technique (hacks) like JSONP.
Question 2: Server side
CORS is a browser thing, to protect web users against malicious JS acting on their behalf (for example, to reconfigure their home router), there is no such thing server side.
When script tries to access a frame from a different origin Chrome blocks it and throws exception as
"Uncaught SecurityError: Blocked a frame with origin 'provider domain' from accessing a frame with origin 'mydomain'. Protocols, domains, and ports must match".
I got this error after some update in google chrome. Any suggestions?
Direct Javascript calls between frames and/or windows are only allowed if they conform to the same-origin policy. If your window and iframe share a common parent domain you can set document.domain to "domain lower") one or both such that they can communicate. Otherwise you'll need to look into something like the postMessage() API.
This is a security update. If an attacker can modify some file in the web server (the JS one, for example), he can make every loaded pages to download another script (for example to keylog your password or steal your SessionID and send it to his own server).
To avoid it, the browser check the Same-origin policy
Your problem is that the browser is trying to load something with your script (with an Ajax request) that is on another domain (or subdomain).
To avoid it (if it is on your own website) you can:
Copy the element on your own server (but it will be static).
You can change your HTTP header to accept Cross-Origin content. See the Access-Control-Allow-Origin documentation for more information.
After reading about CORS (Cross-Origin Resource Sharing), I don't understand how it improves security. Cross-Domain AJAX communication is allowed if the correct ORIGIN header is sent. As an example, if I send
ORIGIN: http://example.com
The server checks if this domain is in the white list and, if it is, header:
Access-Control-Allow-Origin: [received url here]
is sent back, together with the response (This is the simple case, there are also prefighted requests, but the question is the same).
Is this really secure? If someone wants to receive the information, faking an ORIGIN headers seems like a really trivial task. Also the standard says that the policy is enforced in the browser, blocking the response if Access-Control-Allow-Origin is not correct. Obviously if anyone is trying to get that info, he will not use a standard browser to block it.
The purpose is to prevent this -
You go to website X
The author of website X has written an evil script which gets sent to your browser
that script running on your browser logs onto your bank website and does evil stuff and because it's running as you in your browser it has permission to do so.
The ideas is that your bank's website needs some way to tell your browser if scripts on website X should be trusted to access pages at your bank.
Just to add on #jcoder 's answer, the whole point of the Origin header isn’t to protect the resources requested on a server. That task is up to the server itself via other means exactly because an attacker is indeed able to spoof this header with the appropriate tools.
The point of the Origin header is to protect the user.
The scenario is the following:
an attacker creates a malicious website M
a user Alice is tricked to connect to M, which contains a script that tries to perform some actions through CORS on a server B that actually supports CORS
B will probably not have M in its Access-Control-Allow-Origin header, cause why would it?
The pivotal point is that M has no means to spoof or overwrite the Origin header, because the requests are initiated by Alice's browser. So her browser will set the (correct) Origin to M, which is not in the Access-Control-Allow-Origin of B, therefore the request will fail.
Alice could alter the Origin header herself, but why would she, since it would mean she is harming herself?
TL;DR: The Origin header protects the innocent user. It does not secure resources on a server. It is spoofable by an attacker on his own machine, but it cannot be spoofed on a machine not under his control.
Servers should still protect their resources, as a matching Origin header doesn't mean an authorized access. However, a Origin header that does NOT match means an unauthorized access.
You can't fake an Origin header with JavaScript in a web browser. CORS is designed to prevent that.
Outside of a web browser, it doesn't matter. It isn't designed to stop people from getting data that is available to the public. You can't expose it to the public without members of the public getting it.
It is designed so that given:
Alice, a person providing an API designed to be accessed via Ajax
Bob, a person with a web browser
Charlie, a third party running their own website
If Bob visits Charlie's website, then Charlie cannot send JS to Bob's browser so that it fetches data from Alice's website and sends it to Charlie.
The above situation becomes more important if Bob has a user account on Alice's website which allows him to do things like post comments, delete data, or see data that is not available to the general public — since without protection, Charlie's JS could tell Bob's browser to do that behind Bob's back (and then send the results to Charlie).
If you want to stop unauthorized people from seeing the data, then you need to protect it with passwords, SSL client certs or some other means of identity-based authentication/authorization.
The purpose of the same origin policy isn't to stop people from accessing website content generally; if somebody wants to do that, they don't even need a browser. The point is to stop client scripts accessing content on another domain without the necessary access rights. See the Wikipedia entry for Same Origin Policy.
"After reading about CORS, I don't understand how it improves security."
CORS does not improve security. CORS provides a mechanism for servers to tell browsers how they should be accessed by foreign domains, and it tries to do so in a way that is consistent with the browser security model that existed before CORS (namely the Same Origin Policy).
But the Same Origin Policy and CORS have a limited scope. Specifically, the CORS specification itself has no mechanism for rejecting requests. It can use headers to tell the browser not to let a page from a foreign domain read a response. And, in the case of preflight requests, it can ask the browser not to send it certain requests from a foreign domain. But CORS doesn't specify any means for the server to reject (that is, not execute) an actual request.
Let's take an example. A user is logged in to site A via a cookie. The user loads malicious site M, which tries to submit a form that does a POST to A. What will happen? Well, with or without CORS, and with or without M being an allowed domain, the browser will send the request to A with the user's authorization cookie, and the server will execute the malicious POST as if the user initiated it.
This attack is called Cross-Site Request Forgery, and CORS itself does nothing to mitigate it. That's why CSRF protections are so important if you allow requests to change data on behalf of users.
Now, the use of the Origin header can be an important part of your CSRF protection. Indeed, checking it is part of the current recommendation for multi-pronged CSRF defense. But that use of the Origin header falls outside the CORS specification.
In sum, CORS is a useful specification for extending the existing Same Origin Policy security model to other accepted domains. It doesn't add security, and sites need the same kinds of defense mechanisms that they did before CORS.
I am late to answer but I don't think any post here really provides the sought answer. The biggest takeaway should be that the browser is the agent that is writing the origin header value. An evil script cannot write the origin header value. When the server responds back with a Access-Control-Allow-Origin header, the browser tries to ensure that this header contains the origin value sent earlier. If not, it triggers an error and does not return the value back to the requesting script. The other answers to this question present a good scenario to when you would like to deny an answer back to the evil script.
#daniel f also provides a good answer to the question