This is a question about cross-domain API security. The best way to ask this so it could be useful for others is through a hypothetical example.
Domain APIHOST.COM wishes to allow access to its resources to FRIENDLYSITE1.COM and FRIENDLYSITE2.COM (but no other domains)
The FRIENDLYSITEs are owned by others, and APIHOST has no direct server access to them. They may be running any server technology. They are willing to host additional content, but nothing too complicated.
When Bob visits FRIENDLYSITE1.COM using his web browser, his credentials for FRIENDLYSITE1.COM (or APIHOST.COM) are irrelevant. Security should be handled between APIHOST.COM and FRIENDLYSITE1.COM.
I have looked into all of the cross-domain request technologies (CORS, iFrames, JSONP), but all of them assume that the security should come from Bob the browser, and not from the FRIENDLYSITE1.COM domain that Bob is visiting.
Is there a way to do cross-domain API access where the security is handled between the two servers, without involving Bob and his browser?
If you want to secure communication between two servers, then you are going to need to use a secure transport (like https) and use some credentials that are only provided to sites that you wish to allow access.
Those credentials can be as simple as a username and password if you want. In that case, you would provide FRIENDLYSITE1.COM some credentials and whenever it wants to make a connection to APIHOST.COM, it will include those credentials with each API request (or perhaps your API supports a login that creates a cookie that can then be used for subsequent API calls).
If, on the other hand, what you really mean by your question is that there are web pages hosted by FRIENDLYSITE1.COM that contain Javascript in them and that Javascript in those web pages wants to access APIHOST.COM, then that is a different situation. Since this situation is actually connected from the browser on the user's computer (an insecure environment), you using credentials like in the previous example exposes those credentials to anyone and thus they are no longer secret.
About the best you can do in this case is to enable APIHOST.COM for CORS and only allow sites FRIENDLYSITE1.COM and FRIENDLYSITE2.COM for CORs access. This will keep any web pages from any other sites from accessing APIHOST.COM from a browser, but it will not prevent any server or any server proxy from accessing APIHOST.COM. It's basically impossible to allow access from a specific web page, but not from anywhere else. This is because web pages are completely insecure so you can't use credentials from a web page, but keep them secret.
Related
I have a logic written on my server mostly doing curl requests (e.g. accessing social networks). though, some of the sites, will be blocking my server(s) IPs soon.
I can of course, use VPN or deploy multiple servers per location, but it won't get accurate, and still some of the networks might get block the user account.
I am trying to find creative solution to run it from the user browser (it is ok to ask for his permission, as it is an action he is explicitly trying to execute) Though I am trying to avoid extra installations (e.g. downloadable plugins\extension or a desktop app)
Is there a way to turn the client browser into a server-proxy, to run those curl-calls from his machine instead of sending it from my own server? (e.g. using web-sockets, polling, etc.)
It depends on exactly what sort of curl requests you are making. In theory, you could simulate these using an XMLHttpRequest. However, for security reasons these are generally not allowed to access resources hosted on a different site. (Imagine the sort of issues it could cause for instance if visiting any website could cause your browser to start making requests to Facebook to send messages on your behalf.) Basically it will depend on the Cross-origin request policy of the social networks that you are querying. If the requests being sent are intended to be publicly available without authentication then it is possible that your system will work, otherwise it will probably be blocked.
I have clients(A, B) and they use my service.
They have domains and they include same javascript to their websites.
The javascript communicates with my server and saves cookies to the domain.
The cookies are the infomation about a connected user and cookies are different by user.
I assume they use same browser.
So if a user connect to A website and connect to B website, I want to save same key information to their cookies.
Is their way to do this?
You cannot access cookies for other domains, but you can set up a third domain tracking.example, and then request any resource (e.g. a 1pixel image) from that domain.
To read the cookie from one of the websites, either use a CORS-enabled endpoint, e.g. https://tracking.example/getuserid, that allows client-side code on the website to read out the cookie or an ID that is associated with it, or embed an iframe from tracking.example and use inter-frame-communication.
Note that for privacy reasons, third-party cookies are being restricted, or even totally blocked by some browsers and configurations. There is no replacement for third-party cookies, while there are ways to identify users without cookies, they are nowhere near 100% accurate, may violate local laws, and are intended to be by browsers.
If both websites manage logins, you can of course use the logged-in email address as an ID.
I don't really get Access-Control-Allow-Origin and CORS.
If I allow request from any domain to my page, does that imply any security issues for my page?
I always thought, that SOP ensures, that there can't run any script on a page, which requests data from another server, as that data might be malicious. But as the server, which serves the malicious data, can just reply with a header containing Access-Control-Allow-Origin:*, everything can be loaded from that server.
So as soon as somebody manages to inject a piece of JS code into a page, every malicious code can be loaded from a server belonging to the attacker.
Unitl now I assumed, that I would have to enable cross domain requests to allow code on my page to request data from another domain but it seems to be the other way round; the other domain has to allow my domain to request data.
I don't really see the security benefits of this concept.
Could anybody explain the concepts behind this or tell me if I am getting it all wrong?
Given:
Alice, a user with a browser
Bob, a site owner with a website
Mallory, a malicious site owner with a website
Alice has an account on Bob's server. Maybe it is her webmail. Maybe it is her online banking. Maybe it is somewhere she likes to shop.
Alice visits Mallory's website, not knowing that it is evil.
The Same Origin Policy prevents Mallory's website from using JavaScript to tell Alice's browser to make a request to Bob's website and give Alice's personal information (her bank balance for instance) to Mallory's website (and therefore to Mallory).
(Sometimes the request will be blocked because the conditions require a pre-flight request, other times the request will go through but the response will not be provided to Mallory's site. Look up CSRF if you want to defend against attacks where the danger lies in what the server does when it gets the request rather then in information leaking from the response).
CORS allows Bob to say that a resource on his website does not contain any personal information so that it is safe to allow other sites to access it (or that a particular site can be trusted with the personal information).
So as soon as somebody manages to inject a piece of JS code into a page,
XSS is a completely different security problem. You need to prevent people injecting JS.
I have been seeing lot of questions and answers here, but something really not answered my questions
How do I make a cross domain request to a http://otherdomain.com?login.php?username="test"&pass="pass"
I would like to state that, this domain is not controlled by us and it will return normal HTTP response if you actually make a HTTP POST request to the above URL.
So based on the HTTP Response [HTML], I would like to evaluate successful or failure login.
Since it's an internal application, if it's not possible in normal scenario, we can configure internal system browsers to achieve the same [last option].
Can anyone post a link to tutorial/working example?
Note: I don't have control over otherdomain application. It doesn't return a JSON formatted data. The request must be originated from Clients browser, not allowed any proxy due to application dependance on IP address.
See Ways to circumvent the same-origin policy. None of them will meet your requirements.
Preventing Mallory's site from using Alice's site with Bob's credentials (such as his IP address) is the point of the Same Origin Policy. There is no way around this for a web application.
Since it's an internal application
If it is an internal application, then you could look at using a browser extension to access the data. They have less restrictive security policies as they have to be explicitly installed.
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