Javascript HTTP GET and POST - javascript

When initiating a HTTP GET or POST request:
Common browsers do not allow Javacript to call cross domain
So it means that every HTTP request from a given domain the "Host" in the Request header represents the origin host, say foo.com and that it cannot be modified by the client request?
Furthermore, when a request originated from a subdomain, like bar.foo.com then the "Host" in the request header will be "bar.foo.com"
And that this holds true when doing Cross-domain HTTP request, i.e. the "Host" will be foo.com or if from subdomain bar.foo.com, and that the receiving end (the other domain) will see the "Host" as these hosts respectively?

Everything through the HTTP browser sandbox (not just AJAX calls! IFRAMEs have restrictions based on the same conditions, for different things - namely, you can't control the content of an IFRAME on another domain/host/port/proto, just load pages and see the URI of what is loaded. Content in JS is off-limits) is done client-side rather than server-side: your browser will actively refuse to query anything that does not have:
The same hostname (subdomains count as different hostnames)
The same port
The same access method (HTTP or HTTPS)
For AJAX, this leads into a big red "cannot get due to security"-esque error. For some browsers, the request does happen: there is a way to bypass this restriction, using access-control headers. These effectively tell your browser "I'm friendly to x", where x is a wildcard list of domains (and where * means everything).
To figure this one out, browsers will perform the request, and if CORS is not on, will actively fire an exception (XMLHttpRequest: x is not allowed by y). The request, however, has happened.
The obvious solution is to add an Access-Control-Allow-Origin header in order to signify that cross-domain queries to this site are okay. However, bear in mind two things:
Most browsers have it, but some don't (IE8 <.<)
CORS has some little bugs of its own if the URLs are hardcoded in the script (read up on it!)
You'll therefore want a JSONP fallback for IE. However, keep in mind that all this is done client-side and is no guarantee that there aren't any browsers that will actively disregard CORS or the webkit security model. The entire model also relies on client-side Host resolution.

If the question is "Is this true", then then the answer is no.
Browsers do allow JavaScript to create GET and POST requests cross domain. What they don't allow is javascript to read the response from a cross domain request.
The 'Host' in the HTTP header represents the host that the request is being sent to, not the website that caused the host. HOST is necessary because servers are often shared and one server may host many separate websites, so they need to know which one is being requested.
The website that created the website is often (although not always) identified in the 'REFERER' HTTP Header.

A server that supports CORS will inspect the Origin header in the request. The value will be as you described, the server that the request orignates from. In it's reply, the server will send a header called Access-Control-Allow-Origin. If this matches Origin, the browser will accept the response. It obviously also require the browser to support CORS.
Wikipedia have a fairly good explanation of how it works.

The Host HTTP request header is always the domain that the request is going to.
If you're initiating an HTTP GET or POST request using the XMLHTTPRequest method, then it won't let you send the request if the JavaScript code that sends it isn't on the same domain as the URL you're sending a request too - unless the browser supports cross-origin resource sharing.
If the browser does support cross-origin resource sharing (CORS), then it will send your request to other domains, but with an additional Origin header, indicating the site that served the JavaScript making the request. If the server allows the request, it'll respond with an Access-Control-Allow-Origin header, listing the domains it'll accept requests from.

Related

Does Cross-origin resource sharing affect all clients that connect to a web method?

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.

Does "Access-Control-Allow-Origin" help me against if someone points their domain to my server?

Maybe I misunderstood how to fully implement CORS in my server.
Given this screenshot of a request done via Chrome.
We can see that the we are visiting the site shakh.photography, the request URL is a POST ajax request towards /api/get-videos/ but the response contains a Access-Control-Allow-Origin header that mentions a totally different domain.
Even though the webserver respons with a Access-Control-Allow-Origin header, it is ignored by the browser. Everything still works.
I thought only setting the Access-Control-Allow-Origin was sufficient to only allow requests coming from the specified origin.
What have I missed?
Until it's fixed, this situation is testable by visiting shakh.photography.
The request is going to same-origin i.e. shakh.photography/api/.. hence no OPTIONS preflight being sent.
If the request were send from some third party's webpage say third.party then browser would send OPTIONS and server would check for its origin policy and return error as only gamezelle.com is allowed as of now.
If it were sent from gamezelle.com the response would be OK and then browser would send subsequent request.
The Same Origin Policy only stops a site from reading a cross origin Ajax response. This protects against a user's cookies being used by an attacking site to take data from your site using the authority of the user.
CORS allows you to selectively weaken the Same Origin Policy, it isn't used to strengthen it.
We can see that the we are visiting the site shakh.photography, the
request URL is a POST ajax request towards /api/get-videos/ but the
response contains a Access-Control-Allow-Origin header that mentions a
totally different domain.
Even though the webserver respons with a Access-Control-Allow-Origin
header, it is ignored by the browser. Everything still works.
Yes. This is normal. The request is from Site A to Site A. None of the cookies or other credentials the user might have to Site B are available to the Site A (the browser sandboxes them from each other). You simply have a server which responds to both URLs with the same data.
A third party could do that, but they couldn't do it for just your API (except via a proxy, which is a different issue, with even fewer security implications). They'd have to make the whole site available under the other hostname, this shouldn't cause any security worries.
If you don't want that, then configure your server so that it uses Virtual Name Hosting and delivers different sets of content based on the Host header in the request.

is it possible to ignore ajax cookies via javascript

Is there a programmatic way in javascript to ignore cookies sent from the server (without changing browser settings).
We use certain plugins on our web server that will randomly update our security cookie. However this causes issues for some of our URLs and we want to ignore those cookies for some cases.
Our security architect recommended we look into this possibility.
example:
1). create ajax request with URL: www.site.com/abc/comtd
2). ignore any cookies that come back in the response
The only way I can think of is to send the AJAX request from a completely different domain. Because the AJAX would be a Cross-Origin Resource Sharing (CORS) request, any response headers would be denied unless the server sends the access-control-allow-origin header. If the AJAX request is not a CORS request, the browser has to respect all Set-cookie headers it receives per the standard.
its not an option in our case to change domains. We need to pass cookies to the server or the requests will not get through security. If we change domains our security cookies would not get passed. What we want is to pass the cookies but ignore any set-cookie response headers for certain URLs.
I think this is not possible on the browser so I am investigating some Apache server plugins like mod_headers. Maybe we can do it on the server itself. Im closing this question and will open another one related to mod_headers.
Just a thought - if you send the request from a WebWorker - I think that is isolated from the main browser context ?

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 *

Meaning of SOP (same origin policy)

What is the real meaning of SOP (Same Origin Policy)?
I know it means that the Javascript code from one origin cannot accuess resources from another origin. But what exactly does the word "resources" mean? For example:
Javascript code can access IMAGES from another site.
Javascript code cannot make ajax request to another side.
But when you use JSON padding, after completing the loading of a padded script tag, the 3rd party script will call your specified callback -- Javascript code from one site is invoking a method of Javascript code from another. Does this violate SOP?
There are several types but if we don't specify:
SOP refers to a mechanism that governs the ability for JavaScript and other scripting languages to access DOM properties and methods across domains
Here you have an excellent description of different types of SOP.
Same Origin Policy is mainly intended to prevent scripts for other domains to perform AJAX (XMLHTTP) requests in the context of the loaded domain and also restricts sites of other domain to access sites resources like cookies, local storage etc. It is more like a standard specification formulated for security measures and every browser has its own way of implementing it by adhering to specifications.
By saying 'prevent scripts for other domains to perform AJAX (XMLHTTP) requests' I mean the cross-origin requests which don't belong to the same domain.
For example, domain.com and test.domain.com belong to the same domain and the test is subdomain, while test.domain2.com belongs to an entirely different domain.
Now let us consider its security implications:-
1.Let us say a website site1.com has an API call to update the password. When the user inputs the required data an HTTP call is made to the backend and the user's authenticity is validated with the session data contained in cookies.
2)Now with this being said, if the attacker creates a site named site2 and has a javascript code to make an HTTP call to site1's change password endpoint. By browsers default behavior it attaches all the cookie data it has for site1 to the request which makes the HTTP call successful thus allowing attackers to succeed.
3)To be able to mitigate this browsers implemented SOP, which dictates the browsers javascript engine to block any request to cross domains like from site2 to site1 for example, unless instructed to allow to do so.
4)Now in this growing modern world with microservice architectures and multiple subdomains, this will be very problematic. To get around this browsers support cross-origin requests if the API response says so with headers like Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Credentials, etc.
5)To put it forward when the ajax request is made from site2 to site1, the browsers check the API response headers and allows the request if any of these values are present in response:-
Access-Control-Allow-Origin:* or Access-Control-Allow-Origin:site2.com or Access-Control-Allow-Origin:*.site2.com (wildcard entry)
6)With this being said there is a major loophole here, even if the sop policy blocks the request, it actually means that the browser blocks the site2 access to read the response data meaning the request was already made to the server. This scenario is only applicable to a few requests on specific conditions which doesn't trigger pre-flight options call. When the options call is made the browser will not allow the request to go through based on the header response in options call.
7)Now comes the second part to it which is Access-Control-Allow-Credentials. In the server response for options call, if the server sets the header to true all the confidential session data like Authorization header, secure cookies will be added to the cross-origin requests from site2 to site1.
Note:- This header is only added if Access-Control-Allow-Origin is very specific to a domain meaning it will not work for * value in the header. Is the Access-Control-Allow-Origin header is * then browsers SOP policy will kick in and blocks it from allowing the secure data if Access-Control-Allow-Credentials is set to true.
The SOP origin policy doesn't deal with image sources and external script includes. To be able to utilize control over those go through the Content Security Policy (CSP). Using it you could control access to external sites wrt to images, scripts, fonts, styles, etc. You would also be able to block unsafe-inline eval's in site like alert boxes to prevent some XSS attacks. This is new defacto standard and a lot of websites started implementing it.
To be able to prevent such attacks (CSRF attacks), websites also implement a csrf-token along with a form that changes on every state change. Even if attacker somehow makes the request from site2 to site1, the request will not go through as the server at site1 validates the csrf token along with the request, which the attacker cannot access through.
Other measures would add origin-based validation if the origin header is present.
JSONP is designed to allow such a mechanism through callbacks.
Sorry for such a long answer and the topic is far bigger than this. This is just my own understanding of it and let me know if I am wrong anywhere.
JSONP gets around the Same Origin Policy by dynamically adding a script tag to the DOM and calling a predefined function with the remote web service's JSON data as the parameter. The tag is not subject to the same origin policy and therefore can request content cross-domain.
Just like how you can use Google's version of jQuery on your site without violating SOP, you can "include" a script tag that calls a predefined function on the data you receive back from a web service.

Categories

Resources