document.domain same origin policy not working - javascript

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.

Related

Is it possible to send a postMessage to a sandboxed iframe WITHOUT the "allow-scripts" flag?

Basicly I have a cross domain iframe and can't enable the allow-scripts flag, but at the same time I need to get the postMessage that is in a <script> tag in the iframe document OR access the iframe contentDocument.
I've tried:
let iframeElement = document.getElementsByTagName('iframe')[0];
let iframeContent = iframeElement.contentDocument
console.log(iframeContent)
But with the sandbox flag I only get a null return.
What I need to be able to do is one of those three options:
Add a eventListener to a tag that's insde the iframe contentDocument
Get a attr value that's also inside the iframe contentDocument
A way to send a JSON from the origin page and get this JSON in the page with the iframe (postMessage)
But all of this without the allow-scripts flag, is what i'm trying to archieve even possible ?
The simple answer is no.
An <iframe> with its sandbox attribute restricting the use of scripts can not execute scripts. So you won't be able to call postMessage() from this iframe's context, nor will you be able to fire a callback to an event listener.
Now, since your document doesn't satisfies the cross-origin policies, you are stuck, with no way to interact with the <iframe>'s document from outside.
The only workaround, if this feature is a must have, would be to use your server as a proxy so that your iframe's content be actually fetched and served by your own server.
This way, no cross-origin issue anymore (if you add the allow-same-origin policy on your iframe) and you'll be able to access your iframe's content from your parent's doc, or even add event listeners, even though still no scripts could run from this <iframe>'s context, everything would be ran from the main's doc's context. (This means still no postMessage() from the <iframe>).
To quote part of your question,
I need to get the postMessage that is in a <script> tag in the iframe document
If you mean that you need to put or inject a <script> tag which contains postMessaging, then I'm afraid it's not possible because the same-origin policy will prevent it.
If however, you're trying to get access to or listen to a postMessage broadcast from a <script> tag within a cross-origin iframe, then yep, that's exactly what postMessage was designed to achieve. Provided that your message event listener is hosted on the origin as defined in the postMessage's targetOrigin argument.
PostMessage is essentially a contract of trust, to overcome cross-origin barriers; by either having...
access and permission to author the contents of the iframe
been entrusted to listen to broadcasted messages by way of being hosted on the targetOrigin defined (recommended) or by being on any origin if the targetOrigin has a wildcard '*' value (not recommended)
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#Security_concerns

what is the scope of document.domain()?

I understand if we have payment.example.com and news.example.com and they both set document.domain to exmaple.com they can communicate. However, what if en.news.example.com opt-in and set document.domain=example.com? is it also possible to communicate?
Document.domain
Gets/sets the domain portion of the origin of the current document, as used by the same origin policy.
The same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. It is a critical security mechanism for isolating potentially malicious documents.
Example :
// for document www.example.xxx/good.html,
// this script closes the window
var badDomain = "www.example.xxx";
if (document.domain == badDomain)
window.close(); // Just an example - window.close() sometimes has no effect.
var domain = document.domain;
Changing the value of this property is the easiest way to work around the limitations that the same origin policy applies when your pages are on different sub-domains of the same site. While JavaScript would normally consider pages from blog.example.com and from forum.example.com to be from different origins and so not allow JavaScript from one to interact with web pages from the other, you can resolve this particular restriction by setting the document.domain in both pages to the same value. By setting the document.domain to the shortest version of your domain name in all of your scripts you would allow your JavaScript to communicate across all of the pages of your site regardless of protocol, sub-domain or port.

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

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

What are the difference between postMessage() and dispatchEvent() in respect to the origin policy?

I have this code, I have set the MessageEvent 's origin to *, but still the console prompts Blocked a frame with origin "AAAA" from accessing a frame with origin "BBBB". Protocols, domains, and ports must match. Anyone know why?
var size = {
width: document.body.scrollWidth,
height: document.body.scrollHeight
}
var evt = new MessageEvent("dimensionMessage",{
"data": size,
"origin":"*"
});
window.parent.dispatchEvent(evt);
However, if I use window.parent.postMessage(size, "*") , it works.
The error message tells you that a cross-origin iframe cannot in general invoke a method from the parent if it is in a different origin; that includes the dispatchEvent method (otherwise, an iframe could for instance generate mouse events in the parent page).
The postMessage API is an exception to that, designed precisely to allow cross-origin communication in a well-defined manner.
(Setting origin to '*' won't help you here; in general, that property is expected to be set by the browser when a message is sent via postMessage; creating manually a MessageEvent object is mostly only useful when you want to simulate in the receiving page the reception of an external message)
When two documents do not have the same origin, they have very limited access caused by Same-origin policy restrictions.
In your example dispatchEvent() has limited access to a different frame (window.parent).
window.postMessage() allow to perform a cross-window messaging avoiding Same-origin policy restriction.
Parameter targetOrigin for window.postMessage() specifies what the origin of otherWindow must be for the event to be dispatched, either as the literal string "*" (indicating no preference) or as a URI.
Please note that in your production code you should use a specific URI in order to make your code more secure. More information about how to use window.postMessage() securely can be found here https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

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