A confusion about same origin policy(sop) and csrf protection - javascript

I have a confusion about the Same Origin Policy(SOP).
For example, http://bad.com/bad.html with a bad.js, and http://good.com/good.html with a good.js. I open both urls in my chrome with two tabs(tab1, and tab2).
In the good.html(opened in tab2), there is a element <input id="token-id" type='text' name='token' value='123abc'>
Now the question is if there is no SOP, whether it's possible to read the element input value from bad.html(opened in tab1) with some code like document.getElementById('token-id').value() in bad.js.
Another question is if the above question's answer is 'no', I can't understand this sentence in wiki https://en.wikipedia.org/wiki/Same-origin_policy#Security_Concerns.
Regarding the sending of new transactions, even CSRF protections by the banking site have no effect, because the script can simply do the same as the user would do
As we can't get the csrf token. why it does't work. Server can figure the real post request by verify the csrf token.
Do I misunderstand the csrf protection or the SOP itself?
Thanks if anyone can help me figure out these confusion.

Now the question is if there is no SOP, whether it's possible to read the element input value from bad.html(opened in tab1) with some code like document.getElementById('token-id').value() in bad.js.
No — since there is no reference to the other tab.
If the tab being read from was opened via window.open from the tab doing the reading (instead of manually), then the token could be read.
Happily, the Same Origin Policy does exist, so we don't need to worry about that.
Regarding the sending of new transactions, even CSRF protections by the banking site have no effect, because the script can simply do the same as the user would do
The CSRF token contains information only available to the browser and the friendly site.
Since the attacking site can't read the token, the attacking site can't construct a request that includes it. The friendly site can determine that the request constructed by the attacking site is untrustworthy because it doesn't include the token.
If the Same Origin Policy didn't exist, then the attacking site could read the token, which would render the token useless.
Since the Same Origin Policy does exist, that isn't a concern.

You are misunderstanding some things, the SOP says that if you open http://bad.com/bad.html and that page loads and executes bad.js, that javascript can make an AJAX request to bad.com, but any request pointing to good.com will be blocked unless good.com accepts it explicitly (by using CORS protocol).
The reason is that any request to any site may include the cookies that the browser has stored related to that site, so bad.com could use the session that you did not close on good.com to do something harmful.
So regarding your questions: No, a tab is not aware of other tabs unless they are related (parent - child), so a page cannot modify the behavior of another one. And the SOP ensures that a page cannot impersonate as another one

Related

Capture jQuery $.ajax error (or Browser console error) in Javascript [duplicate]

This question is related to Cross-Origin Resource Sharing (CORS, http://www.w3.org/TR/cors/).
If there is an error when making a CORS request, Chrome (and AFAIK other browsers as well) logs an error to the error console. An example message may look like this:
XMLHttpRequest cannot load http://domain2.example. Origin http://domain1.example is not allowed by Access-Control-Allow-Origin.
I'm wondering if there's a way to programmatically get this error message? I've tried wrapping my xhr.send() call in try/catch, I've also tried adding an onerror() event handler. Neither of which receives the error message.
See:
http://www.w3.org/TR/cors/#handling-a-response-to-a-cross-origin-request
...as well as notes in XHR Level 2 about CORS:
http://www.w3.org/TR/XMLHttpRequest2/
The information is intentionally filtered.
Edit many months later: A followup comment here asked for "why"; the anchor in the first link was missing a few characters which made it hard to see what part of the document I was referring to.
It's a security thing - an attempt to avoid exposing information in HTTP headers which might be sensitive. The W3C link about CORS says:
User agents must filter out all response headers other than those that are a simple response header or of which the field name is an ASCII case-insensitive match for one of the values of the Access-Control-Expose-Headers headers (if any), before exposing response headers to APIs defined in CORS API specifications.
That passage includes links for "simple response header", which lists Cache-Control, Content-Language, Content-Type, Expires, Last-Modified and Pragma. So those get passed. The "Access-Control-Expose-Headers headers" part lets the remote server expose other headers too by listing them in there. See the W3C documentation for more information.
Remember you have one origin - let's say that's the web page you've loaded in your browser, running some bit of JavaScript - and the script is making a request to another origin, which isn't ordinarily allowed because malware can do nasty things that way. So, the browser, running the script and performing the HTTP requests on its behalf, acts as gatekeeper.
The browser looks at the response from that "other origin" server and, if it doesn't seem to be "taking part" in CORS - the required headers are missing or malformed - then we're in a position of no trust. We can't be sure that the script running locally is acting in good faith, since it seems to be trying to contact servers that aren't expecting to be contacted in this way. The browser certainly shouldn't "leak" any sensitive information from that remote server by just passing its entire response to the script without filtering - that would basically be allowing a cross-origin request, of sorts. An information disclosure vulnerability would arise.
This can make debugging difficult, but it's a security vs usability tradeoff where, since the "user" is a developer in this context, security is given significant priority.

CORS fetch authentication using Browser's session cookie

I have a server that stores session cookies and you can log onto it using a page (foo.com/login.html) that runs in the browser. The browser then stores a session cookie for this domain.
Now I want another page (bar.com) upon initialization to make a GET request using JavaScript to the first page (foo.com/authenticate) which should check if a session cookie exists in the browser and validate it, if correct he should respond with the session's username (however this is retrieved from the cookie). Of course I cannot check in bar.com's JavaScript if there exists a session cookie for foo.com.
Trying to solve this I ran into a few problems, one of which is of course CORS. I managed to avoid this problem by placing a reverse proxy in front of foo.com that adds all required CORS headers to the response. besides adding the headers, the proxy only tunnels requests through (eg. rev-proxy.com/authenticate -> foo.com/authenticate)
Now when I call the handler through the rev proxy from just another browser window directly (eg. rev-proxy.com/authenticate), I get the correct response. The handler from foo.com's backend finds the session cookie, reads out the username and passes it back. BUT when I try to make the same call from JavaScript inside bar.com (fetch("rev-proxy.com/authenticate")), I receive null, meaning he did not find the cookie (note that the request itself has status 200, meaning it did reach the backend of foo.com).
I have the feeling I am missing a crucial point in how cookies are used by browsers but I cannot find any useful information on my specific problem since I believe it is a rather unusual one.
See the MDN documentation:
fetch won’t send cookies, unless you set the credentials init option. (Since Aug 25, 2017. The spec changed the default credentials policy to same-origin. Firefox changed since 61.0b13.)

Why if this API gives the "No Access-Control-Allow-Origin header", can I access it through the address bar or http://www.hurl.it

EDIT: See: https://softwareengineering.stackexchange.com/questions/216605/how-do-web-servers-enforce-the-same-origin-policy for a great explanation on why browsers enforce Access-Origin restrictions but servers (like Hurl.It) are not restricted.
I'm trying to use the API found here http://forismatic.com/en/api/. But I am getting the "No 'Access-Control-Allow-Origin' header" error. If that is the case, why can I access the API by entering the URL with its parameters directly into the address bar of my browser, or through http://www.hurl.it ? I am using codepen if that affects anything.
My code is below. Thank you very much, I've been searching around for a few hours but I'm at a dead end.
var quoteRequest = new XMLHttpRequest();
quoteRequest.open("GET", "http://www.api.forismatic.com/api/1.0/?method=getQuote&format=json&lang=en", true);
quoteRequest.send();
var quote = JSON.parse(quoteRequest.responseText);
If that is the case, why can I access the API by entering the URL with its parameters directly into the address bar of my browser, or through http://www.hurl.it ?
Because that's how the Same Origin Policy works: It applies to ajax requests, not direct requests (typing it in to the address bar) or server-side requests (what Hurl-It does).
The purpose of the SOP is to prevent Page A using Page B's resources within Page A, from within the browser. This is primarily to protect the user, since when the browser requests resources from Page B, it may use the user's session or other credentials, revealing information to Page A's code that it should have access to. apsillers has a great explanation of this over on programmers.stackexchange.com; here's an excerpt:
For example, suppose I accidentally load http://evil.com/, which sends a request for http://mail.google.com/. If the SOP were not in place, and I was signed into Gmail, the script at evil.com could see my inbox. If the site at evil.com wants to load mail.google.com without my cookies, it can just use a proxy server; the public contents of mail.google.com are not a secret (but the contents of mail.google.com when accessed with my cookies are a secret).
If that API doesn't grant access to your origin (your page), and doesn't offer a JSONP alternative, you can only use it indirectly, via a server in the middle (your own server, or Hurl-It, etc.).

document.domain same origin policy not working

Despite of the fact that I have seen many articles (including in stackoverflow) demonstrating up how to bypass javascript's same origin policy assigning document.domain property, its not working. I also read in W3C specs that document.domain property is read-only and not all browsers accept setting it and I think that is the cause I can't get that working!
I have a page (domain d1.y.com.br) and I need to invoke a button in an embedded iframe's page (domain d2.x.com.br). I'm setting the parent document.domain attribute to subdomain 'x.com.br' but I'm still receiving the 'access denied' error message in firebug console.
I have also read about JSONP but its not the case here. I really need to interact with iframe's DOM and not only get data from there (using proxy service).
Does really exist any way to bypass same origin policy to interact with the iframe's DOM ???
The proper way to send data between iframes (especially across domains) is using postMessage(). https://developer.mozilla.org/en-US/docs/Web/API/window.postMessage
That effectively "bypasses" the problem by having the recipient of the message verify that the caller has the correct domain - based on whatever rules it wants.

How does the browser / JavaScript same origin policy apply to two-level domain names?

I have some JavaScript that is sharing a request between two separate servers on the same domain.
Is .com a requirement for the domain in JavaScript?
In this case both the servers are on the .abc.tyy domain with the tyy being what would normally be .com
Wondering if I can only use .com for the domain? I am getting a permission denied error, but this code works fine on other separate servers on the same domain(.com).
Updated:
Here is exactly how I'm using this:
123.abc.tyy has a script that loads properties that I want to access.
The script on 123.abc.tyy at opening script tag, sets the document.domain to 'abc.tyy'.
When I call the 'getUser()' function in 123.abc.tyy's script FROM 234.abc.tyy I am getting a permission denied error.
The way I am calling 'getUser()' is:
I access http://123.abc.tyy in a browser, and the site allows me to specify a URL to load in one of it's frames. I point that URL to http://234.abc.tyy/BeginLoadPatient.aspx" in that page I am doing the following:
window.location = 'http://234.abc.tyy/LoadPatient.aspx?PatientId=' + getUser() '; with getUser being a function originating in 123.abc.tyy
If I add 234.abc.tyy and 123.abc.tyy to my trusted sites, everything works fine - is this skipping over the same origin policy?
No, the SOP doesn't care what the domain is, only that it represents the same origin. (Could it be that you have the .com domain hard-coded somewhere?)
Note that there's more than the domain to consider. The Same Origin Policy looks at protocol, port, and host as well. So aaa.abc.tyy and bbb.abc.tyy are different origins.
If you're in control of the servers involved, you might look at Cross-Origin Resource Sharing, but unfortunately CORS is only implemented in modern browsers (and on those versions of IE where it's supported, it's only supported if you use it explicitly).
Another option, of course, is JSON-P, which has the advantage of working cross-browser right now.
Another thing to look at is document.domain, details here and here.
Update after your edits:
The script on 123.abc.tyy at opening script tag, sets the document.domain to 'abc.tyy'.
When I call the 'getUser()' function in 123.abc.tyy's script FROM 234.abc.tyy I am getting a permission denied error.
You'll need to set document.domain to "abc.tyy" in BeginLoadPatient.aspx as well.
If I add 234.abc.tyy and 123.abc.tyy to my trusted sites, everything works fine - is this skipping over the same origin policy?
I wouldn't be at all surprised (although to me it would be pretty dodgy), but have no first-hand knowledge of it. Would be easy to test.

Categories