Ajax Cross domain request to non-controlled domain - javascript

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.

Related

CORS error with Javascript but not with Python/PHP

I'm writing a small script to access an external API for work. I originally did this in Python and everything worked fine.
I was then asked to try and do it in Javascript. Now, I'm no programmer really, but I do know (or believe) that Javascript is largely for client-side, whereas PHP or Python are really for server-side operations. When I wrote the script in Python I had no problems, but in Javascript I get a
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
error. From what I've read about CORS here and similar questions on Stack, that makes sense, but I don't really understand why I don't get a similar error in Python or PHP...
I'm fairly new to this so I'm probably missing a number of things, but I'd really appreciate any insight anyone can give me. If I've left out any important info, please let me know.
From Mozilla's documentation:
For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and Fetch follow the same-origin policy. So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain.
Since Javascript in the browser uses XMLHttpRequest and fetch to make HTTP requests, they're subject to CORS policy enforcement.
More information on the reasons for CORS:
CORS is intended to allow resource hosts (any service that makes its data available via HTTP) to restrict which websites may access that data.
Example: You are hosting a website that shows traffic data and you are using AJAX requests on your website. If SOP and CORS were not there, any other website could show your traffic data by simply AJAXing to your endpoints; anyone could easily "steal" your data and thus your users and your money.
The external API you're using likely implemented a CORS policy intentionally. For example, if the API requires an application-level secret key for authentication, a CORS policy would discourage the use of that key in a public environment (namely the browser). Alternatively, the API may have a list of acceptable domain names for CORS that doesn't include the domain you're currently using.
Those are just a few examples; there could be any number of reasons for an API to implement CORS headers.

Cross-Domain API Access Security

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.

Why is there no same-origin policy for WebSockets? Why can I connect to ws://localhost?

I'd like to use WebSockets for inter-process communication for my application (Daemon<->WebGUI and Daemon<->FatClient, etc.). During testing, I tried connecting to my locally running web socket server (ws://localhost:1234) via the JavaScript WebSocket client on websocket.org (http://www.websocket.org/echo.html).
My question now is:
Why is this possible? Is there no cross-origin policy implemented in the browsers (here: FF29 on Linux)?
I am asking because if websocket.org was evil, it could try to communicate with my local WS server and redirect every message it receives from localhost to any other server:
Local WebSocket Server Browser Evil Web Server
at ws://localhost:1234 at http://evil.tld
| | |
| |------[GET /]--------->|
| |<-----[HTML+EvilJS]----|
|<------[connect ws://..]----| |
|<----[some communication]-->| |
| |----[evil forward]---->|
| | |
I have not tested the entire use case, but the connect to ws://localhost from the JS delivered by websocket.org definitely works.
To address the "Why?" part, the reason why browsers don't enforce the Same Origin Policy (of which CORS is a relaxation) for WebSockets as opposed to AJAX calls, is because WebSockets were introduced after the value of cross-origin requests was established, and because they're not subject to SOP to begin with, the historical reason for the CORS client-side checks doesn't apply.
For AJAX, in the days of a blanket Single Origin Policy, servers never expected an authenticated browser to send a request from a different domain1, and so didn't need to ensure the request was coming from a trusted location2, just check the session cookie. Later relaxations like CORS had to have client-side checks to avoid exposing existing applications to abuse by violating this assumption (effectively doing a CSRF attack).
If the Web were being invented today, knowing what we know now, neither SOP nor CORS would be required for AJAX and it's possible that all the validation would be left to the server.
WebSockets, being a newer technology, are designed to support cross-domain scenarios from the get go. Anyone writing server logic should be aware of the possibility of cross-origin requests and perform the necessary validation, without the need for heavy-handed browser-side precautions à la CORS.
1 This is a simplification. Cross-origin GET requests for resources (including <img>, <link> and <script> tags) and form submission POST requests were always permitted as a fundamental feature of the Web. Nowadays, cross-origin AJAX calls whose requests have the same properties are also permitted and known as simple cross-origin requests. However, accessing the returned data from such requests in code is not allowed unless explicitly permitted by the server's CORS headers. Also, it is these "simple" POST requests that are the primary reason why anti-CSRF tokens are necessary for servers to protect themselves from malicious websites.
2 In fact, a secure way to check the request source wasn't even available since the Referer header can be spoofed e.g. using an open redirect vulnerability. This also shows how poorly CSRF vulnerabilities were understood back then.
oberstet answered the question. Thank you! Unfortunately I can't mark it as "correct" because it was a comment. The browser sends the "origin" header which can be checked by the application.
In Java [1]:
#Override
public void onOpen(WebSocket clientSocket, ClientHandshake handshake) {
String clientOrigin = handshake.getFieldValue("origin");
if (clientOrigin == null || !clientOrigin.equals(WEBSOCKET_ALLOWED_ORIGIN_HEADER)) {
logger.log(Level.WARNING, "Client did not sent correct origin header: " + clientOrigin);
clientSocket.close();
return;
}
// ...
}
[1] using https://github.com/TooTallNate/Java-WebSocket
WebSockets can cross domain communication, and they are not limited by the SOP (Same Origin Policy).
The same security issue you described can happen without WebSockets.
The evil JS can:
Create a script/image tag with a URL to evil.tld and put data in the query string.
Create a form tag, put the data in the fields, and invoke the "submit" action of the form, doing an HTTP POST, that can be cross domain. AJAX is limited by the SOP, but normal HTTP POST is not. Check the XSRF web security issue.
If something injects javascript in your page, or you get malicious javascript, your security is already broken.

Security implications of adding all domains to CORS (Access-Control-Allow-Origin: *)

It is said that instead of adding all domains to CORS, one should only add a set of domains.
Yet it is sometimes not trivial to add a set of domains. E.g. if I want to publicly expose an API then for every domain that wants to make a call to that API I would need to be contacted to add that domain to the list of allowed domains.
I'd like to make a conscious trade off decision between security implications and less work.
The only security issues I see are DoS attacks and CSRF attacks.
CSRF attacks can already be achieved with IMG elements and FORM elements.
DoS attacks related to CORS can be overcome by blocking requests upon the referrer header.
Am I missing security implications?
===Edit===
It is assumed that the Access-Control-Allow-Credentials Header is not set
I know how to add a given list of domains "CORS access" and I'm therefore only interested in the security implications of adding all domains "CORS access"
Cross-Site Request Forgery attacks are far and away the primary concern that Access-Control-Allow-Origin addresses.
Ryan is certainly correct regarding content retrieval. However, on the subject of making the request there is more to say here. Many web sites now provide RESTful web services that expose a wide range of features that may involve making significant changes in the backend. Very often, these RESTful services are intended to be invoked with an XHR (e.g. AJAX) request (probably with a "Single Page Application" as the front-end). If a user has an active session granting access to these services when they visit a malicious third-party site, that site may try to invoke those REST endpoints behind the scenes, passing in values that could compromise the user or the site. Depending on how the REST services are defined, there are various ways to protect against this.
In the specific case of REST web services for a Single Page App, you can dictate that all requests to the backend REST endpoints are made with XHR and refuse any non-XHR request. You can dictate this by checking for the presence of a custom request header (something like jQuery's X-Requested-With). Only XHR-type requests can set these headers; simple GET and POST requests from forms and embedded resources cannot. Finally, the reason that we want to dictate XHR requests gets us back to the original question - XHR requests are subject to CORS rules.
If you allowed Access-Control-Allow-Origin: *, then any site could make any AJAX request on the user's behalf to your REST endpoints. If your REST endpoints involve any kind of sensitive data or allow for data persistence, then this is an unacceptable security vulnerability. Instead, enforce XHR-only requests like I described and define a whitelist of origins allowed to make those requests.
It's worth pointing out that if your REST endpoints do not expose any sensitive information, or if they don't allow the user to make any persistent data changes, then Access-Control-Allow-Origin: * may be the appropriate decision. Google Maps for instance provides read-only views into public map data; there is no reason to restrict the third party sites that may wish to invoke those services.
Old question, but a lot of bad answers here so I have to add mine.
If you don't set Access-Control-Allow-Credentials, and you do cookie-less authentication (ie the caller supplies a Bearer Authorization header) then you don't need to whitelist origins. Just echo the origin back in Access-Control-Allow-Origin.
A well-structured REST API can be called safely from any origin.
You can send more than one, like:
Access-Control-Allow-Origin: http://my.domain.com https://my.domain.com http://my.otherdomain.com
but I would advise against it. Instead, keep a whitelist of allowed domains. Lets say:
allowed = [ "X", "Y", "A.Z" ];
Then if you get a request from X you respond with:
Access-Control-Allow-Origin: X
If you get a request from A.Z you respond with:
Access-Control-Allow-Origin: A.Z
If you get a request from a domain that is not allowed, respond with an error or no CORS policy.
All XHR requests will send an Origin header, so use that. And you only need to send the CORS policy headers for the OPTIONS request, not the GET/POST/HEAD request that follows.
The main issue I see is that you expose all your domains. Maybe you have a secure admin domain like: https://admin.mydomain.com, or maybe you have a product website that isn't ready for launch yet. You don't want to include anything that isn't absolutely necessary for the request at hand.
And * is just extremely lazy.
CORS is about getting content back, not just making the request. When you get a resource through an img or script tag, you can trick someone's browser into making a CSRF style request. This is normal, and you can protect against that with a normal CSRF token.
With CORS enabled on all domains, you can now have javascript on an attacking site make a request and get back the content, invading their privacy.
Example:
Imagine your back enables CORS for all domains. Now I make a website that makes a request to yourimaginarybank.com/balance
An IMG request would do nothing, because my javascript can't get what was in the html of that page on your bank's website. Now that they have turned on CORS, the javascript on my site actually gets back an HTML page with your balance on it, and saves it to my server. Not only can I make a GET request like before, but now I can see what is inside. This is a huge security problem.
How to solve the problem without adding a big list into your headers? Each CORS request is made with the Origin header. The best solution is probably to read the Origin header then query a database to see if it is whitelisted as suggested by Fritz in his answer.
Except of csauve's one, none of the replies answer my original question.
To answer my question; It seems that as long as Access-Control-Allow-Credentials is not set then there is no security problem.
(Which makes me wonder why the spec requires preflight when Access-Control-Allow-Credentials is not set?)
Best Practice is to first check the domain of the incoming request and then generate the response header. Depending on whether this domain is allowed to send requests, you add it (just this one) to the Access-Control-Allow-Origin response header.
Afaik, it is not even possible to add more than one domain to this header. So it's either * or one specific domain and I would always prefer not to add *

Is CORS a secure way to do cross-domain AJAX requests?

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

Categories

Resources