access-control-allow-origin issue on Image load - javascript

Why we do not get access-control-allow-origin issue when we have img tag
src=urlOfdifferentDomain element refers to different domain
like case:1
<img src="urlOfdifferentDomain" />
but we will get same error when we do case 2
//creating image element
a=new Image();
// image on load function
a.onload=function(){
}
// assigning src function
a.src=urlOfdifferentDomain
I just want to know what is the difference between these two approaches .
I also assign csp img-src in webserver to self then also image getting loaded from different domain in case 1

Case 1 is OK because the use of image in HTML does not expose the resource (from other domain) to JavaScript, thus no security problem is caused.
Case 2 will report error because the use of Image object DO bring security risks for some operation such as Canvas editing, as it exposes resource from other domain to JavaScript.
UPDATE: This error is caused by browser security check. The web server doesn't know whether the request comes from html tag or from javascript call, and will return the resource anyway -- you can check the Network debug panel in browser, and see that the resource is downloaded with status 200. After the resource is downloaded and exposed to JavaScript operation. Browser will check whether the JavaScript operation on the resource has vulnerability. If yes, Access-Control-Allow-Origin error will be reported if CORS is not enabled in server.

Related

Allowing cross-site requests between subdomains without changing file contents of second sub domain

I am currently attempting to wrap a web application (ConnectWise) for inclusion within my company's central intranet site. It's a fairly simple process for the most part; create a containing page, with an iframe, point the iframe at the ConnectWise url. This part works for almost all of the functionality.
The problem comes during certain select features of the app (in this case, part of the process of creating a timesheet entry), which simply fail to work. Chrome gives the following console output.
Uncaught SecurityError: Failed to read the 'frame' property from 'Window': Blocked a frame with origin "https://app.example.com" from accessing a frame with origin "https://host.example.com". Protocols, domains, and ports must match.
I am aware this is caused by the security options for cross-site and same-origin policies. Given the following points, is there a way to overcome this?
I have full control over https://host.example.com
I can change html, javascript, and file contents
I can change IIS settings and headers
I have partial control over https://app.example.com
I can not change html, javascript, and file contents
I can change IIS settings and headers.
I have tried setting the Access-Control-Allow-Origin on each server, which so far is the only method I've come across that does not involve being able to change the file contents for the app server. This does not appear to work when given the settings (and combinations of settings) of
* or https://app.example.com while on https://host.example.com
* or https://host.example.com while on https://app.example.com
Edit:
The solution to this "duplicate" question is not applicable here. I do not have access to change file contents (including javascript) of the iframed page (app.example.com). Additionally, the script requiring the permission to run is the page within the iframe, not the page hosting the iframe.
CORS headers such as Access-Control-Allow-Origin only affect AJAX requests, not DOM access.
However, If they are both on the same domain but different subdomains then you can include the following on each page:
document.domain = 'example.com';
From MDN:
One document is allowed to access another if they have both set
document.domain to the same value, indicating their intent to
cooperate
If app.example.com has any script includes to host.example.com then you could put the above code in those scripts to set the domain.
e.g.
<script src="https://host.example.com/setup.js"></script>
No, it is not possible.
Access-Control-Allow-Origin primarily affects getting raw data from HTTP requests, not live DOMs.
postMessage can let frames on different origins communicate, but it requires JS to be included on both pages.

Blocked from accessing an Iframe with origin 'null'

I am using an iframe for a pseudo-ajax file upload. The iframe is in the same view as the upload javascript:
<iframe id="upload_iframe" name="upload_iframe" style="position: absolute; left: -999em; top: -999em;"></iframe>
his works 'nicely' on my local machine, but when I deploy to an Azure web site, I get the following error in Chrome's debug console:
Uncaught SecurityError: Failed to read the 'contentDocument' property
from 'HTMLIFrameElement': Blocked a frame with origin
"https://acme.azurewebsites.net" from accessing a frame with origin
"null". The frame requesting access has a protocol of "https", the
frame being accessed has a protocol of "data". Protocols must match.
I understand this iframe to be same-origin, as it is strictly local, but how do I convince the browser that it is local? That is, is there something I should be doing to the origin and protocol of my iframe to avoid this error?
This is my code, in a nutshell:
dataAccess.submitAjaxPostFileRequest = function (completeFunction) {
$("#userProfileForm").get(0).setAttribute("action", $.acme.resource.links.editProfilePictureUrl);
var hasUploaded = false;
function uploadImageComplete() {
if (hasUploaded === true) {
return;
}
var responseObject = JSON.parse($("#upload_iframe").contents().find("pre")[0].innerText);
completeFunction(responseObject);
hasUploaded = true;
}
$("#upload_iframe").load(function() {
uploadImageComplete();
});
$("#userProfileForm")[0].submit();
};
The form userProfileForm has its target property set to the iframe. This upload arrangement seems to work for most requests, and I don't know if the 'uncaught exception' message is just an observation on Chrome's part, or a potential show stopper. Is there not perhaps a way I can 'catch and ignore' such an exception, and just display a generic message if this happens?
This may depend on your browser, but the IFRAME element is generally not supported for the data protocol, see Wikipedia entry:
http://en.wikipedia.org/wiki/Data_URI_scheme
It may have worked on localhost because localhost can use different authentication & authorization methods (for example on Windows it may run as a trusted site, and may pass your windows user credentials to server automatically, etc.). Same origin I believe means protocol, host, and port must all match. Since data protocol is different than https this is not same origin, hence the security error.
Usually the data protocol is only supported by these elements:
object (images only) (ie: not activeX controls)
img
input type=image
link
CSS declarations that accept a URL
Can you post more of your code and problem statement? There are multiple other ways to accomplish file uploads. For example, traditional POST method (single file), HTML5 method (multi files), or even using javascript to send a stream of bytes to a web service (I did this once in an ActiveX control that used TWAIN to scan documents on user's computer and then upload the scanned image to the website).

CORS: PHP bypass not working

I'm working on a Chrome extension part of which is a function which manipulates images on a page using canvas and its context.getImageData function. That's when I ran into CORS issues. It's my understanding that a server serving an image has to server said image with appropriate CORS headers in order for cross-domain requests to be successful. I started reading up on this (to me) new and unfamiliar technology (tutorial). A substantial number of servers doesn't employ CORS and it's very important for the function of my extension that every image is processed. I've spent a whole day trying to circumvent this issue using client-side scripting but came to the conclusion that the only way is to send the image url to a server and then serve it back with the needed CORS headers (Access-Control-Allow-Origin: *). Now before I get into explaining my implementation I'd like to quote a paragraph from the tutorial page I linked previously.
Cross-Domain from Chrome Extensions
Chrome extensions support cross-domain requests in a two different ways:
Include domain in manifest.json - Chrome extensions can make cross-domain requests to any domain if the domain is included in the "permissions" section of the manifest.json file:
"permissions": [ "http://*.html5rocks.com"]
The server doesn't need to include any additional CORS headers or do any more work in order for the request to succeed.
This should mean that "permissions": "<all_urls>" should circumvent same origin policy restrictions. However, this does not work.
My solution
An XMLHttpRequest passes the image url and callback function to the server on localhost (for testing purposes) which first sets the appropriate header:
header('Access-Control-Allow-Origin: *');,
and then prints a JSON encoded array containing image width, height, and using file_get_contents, imagecreatefromstring, and base64_encode, the equivalent of context.getImageData and a call to the callback function.
The callback function sets the src property of an Image Object (that has crossOrigin set to Anonymous) which is used for drawing the images onto the canvas and sets it's width and height properties.
Result
The expected result was for every image to be loaded and processed without raising a Cross-origin image load denied by Cross-Origin Resource Sharing policy error, however now every image seems to be served without the needed CORS headers crippling my extension. I checked the headers the page on localhost which processes this request sends and it seems to be okay. (screenshot)
Conclusion
My implementation of this solution seems like it should work and I really have no idea why it doesn't. The server is sending the Access-Control-Allow-Origin header, the image data is good and the callback function is called. This is the only issue left to resolve before release. This is a really intriguing issue. I realise the header I'm sending isn't the only one I might want to send but it's sufficient for testing purposes.
I hope this question was clear, and detailed enough for someone to help me resolve this issue. Please do not hesitate to ask for more information and/or code snippets as I didn't really include any code in an attempt to keep this concise.
If your image src is a data uri (base64 encoded image data), then there is no headers to set access control.
Just set the image source to the url you're calling in ajax and send back the image not encoded(echo file_get_contents).

error : Permission denied to access property 'document'

How can I fix this message in Firefox? I am using an Iframe which has an anchor tag? I would like to get a reference to this anchor but i am getting this error when I am trying to access anchor:
var frameWindow = document.getElementById('myIframe').contentWindow;
var anchor = frameWindow.document.links[0]; //.getElementsByClassName('a');
anchor.onclick....
Relaxing the same-origin policy
In some circumstances the same-origin policy is too restrictive, posing problems for large websites that use multiple subdomains. Here are four techniques for relaxing it:
document.domain property
If two windows (or frames) contain scripts that set domain to the same value, the same-origin policy is relaxed for these two windows, and each window can interact with the other. For example, cooperating scripts in documents loaded from orders.example.com and catalog.example.com might set their document.domain properties to “example.com”, thereby making the documents appear to have the same origin and enabling each document to read properties of the other. This might not always work as the port stored in the internal representation can become marked as null. In other words example.com port 80 will become example.com port null because we update document.domain. Port null might not be treated as 80 ( depending on your browser ) and hence might fail or succeed depending on your browser.
Cross-Origin Resource Sharing
The second technique for relaxing the same-origin policy is being standardized under the name Cross-Origin Resource Sharing. This draft standard extends HTTP with a new Origin request header and a new Access-Control-Allow-Origin response header. It allows servers to use a header to explicitly list origins that may request a file or to use a wildcard and allow a file to be requested by any site. Browsers such as Firefox 3.5 and Safari 4 use this new header to allow the cross-origin HTTP requests with XMLHttpRequest that would otherwise have been forbidden by the same-origin policy.[7]
Cross-document messaging
Another new technique, cross-document messaging allows a script from one page to pass textual messages to a script on another page regardless of the script origins. Calling the postMessage() method on a Window object asynchronously fires an "onmessage" event in that window, triggering any user-defined event handlers. A script in one page still cannot directly access methods or variables in the other page, but they can communicate safely through this message-passing technique.
JSONP
JSONP allows a page to receive JSON data from a different domain by adding a <script> element to the page which loads a JSON response from a different domain.
The function call is the "P" of JSONP—the "padding" around the pure JSON, or according to some the "prefix". By convention, the browser provides the name of the callback function as a named query parameter value, typically using the name jsonp or callback as the named query parameter field name, in its request to the server, e.g.,
<script type="application/javascript"
src="http://server2.example.com/Users/1234?jsonp=parseResponse">
</script>
In this example, the received payload would be:
parseResponse({"Name": "Foo", "Id": 1234, "Rank": 7});
If the iframe points to a different domain, you will get this error. This is an example of your browser preventing cross-site scripting: http://en.wikipedia.org/wiki/Cross-site_scripting
The error is due to the same-origin policy like explained in other answers. I post this answer as a workaround to execute JavaScript code in a web console.
My comment suggesting to use Firebug CD command no longer works because Firebug is not supported anymore.
But there is a similar feature in Firefox Developer Tools, you can switch the domain name by selecting the iframe context picker button like described here: https://developer.mozilla.org/en-US/docs/Tools/Working_with_iframes

"Access is denied" error on accessing iframe document object

For posting AJAX forms in a form with many parameters, I am using a solution of creating an iframe, posting the form to it by POST, and then accessing the iframe's content.
specifically, I am accessing the content like this:
$("some_iframe_id").get(0).contentWindow.document
I tested it and it worked.
On some of the pages, I started getting an "Access is denied" error. As far as I know, this shouldn't happen if the iframe is served from the same domain.
I'm pretty sure it was working before. Anybody have a clue?
If I'm not being clear enough: I'm posting to the same domain. So this is not a cross-domain request. I am testing on IE only.
P.S. I can't use simple ajax POST queries (don't ask...)
Solved it by myself!
The problem was, that even though the correct response was being sent (verified with Fiddler), it was being sent with an HTTP 500 error code (instead of 200).
So it turns out, that if a response is sent with an error code, IE replaces the content of the iframe with an error message loaded from the disk (res://ieframe.dll/http_500.htm), and that causes the cross-domain access denied error.
Beware of security limitations associated to iFrames, like Cross domain restriction (aka CORS). Below are 3 common errors related to CORS :
Load an iFrame with a different domain. (Ex: opening "www.foo.com" while top frame is "www.ooof.com")
Load an iFrame with a different port: iFrame's URL port differs from the one of the top frame.
Different protocols : loading iFrame resource via HTTPS while parent Frame uses HTTP.
My issue was the X-Frame-Options HTTP header. My Apache configuration has it set to:
Header always append X-Frame-Options DENY
Removing it allowed it to work. Specifically in my case I was using iframe transport for jQuery with the jQuery file upload plugin to upload files in IE 9 and IE 10.
I know this question is super-old, but I wanted to mention that the above answer worked for me: setting the document.domain to be the same on each of the pages-- the parent page and the iframe page. However in my search, I did find this interesting article:
http://softwareas.com/cross-domain-communication-with-iframes
Note if you have a iframe with src='javascript:void(0)' then javascript like frame.document.location =... will fail with Access Denied error in IE. Was using a javascript library that interacts with a target frame. Even though the location it was trying to change the frame to was on the same domain as parent, the iframe was initially set to javascript:void which triggered the cross domain access denied error.
To solve this I created a blank.html page in my site and if I need to declare an iframe in advance that will initially be blank until changed via javascript, then I point it to the blank page so that src='/content/blank.html' is in the same domain.
Alternatively you could create the iframe completely through javascript so that you can set the src when it is created, but in my case I was using a library which reqired an iframe already be declared on the page.
Basically, this error occurs when the document in frame and outside of ii have different domains. So to prevent cross-side scripting browsers disable such execution.
if it is a domain issue (or subdomain) such as www.foo.com sending a request to www.api.foo.com
on each page you can set the
document.domain = www.foo.com
to allow for "cross-domain" permissions

Categories

Resources