Is there a way to globally catch mixed content errors?
To be clear: I don't want to allow the insecure content, all I want to do is handle the error gracefully.
Backstory: I'm integrating programmatic ads, that is i have to include some script tag, which returns some more JavaScript, which can load even more resources, etc...
It is impossible for me to control, what's coming to my website and sometimes those resources include http resources, which throw a mixed content error. I#m then left with an empty ads container, which looks kind of ugly. Also, I could try to resell this ad-space, since the first try failed.
I already tried window.onerror, but with no avail.
There is no way to catch mixed content warnings, as they have no relation to JavaScript and are handled by your browser instead.
What you can do instead is use Upgrade-Insecure-Requests header to prevent browser from loading unsafe content entirely. And, depending on your use case, you may use MutationObserver to react to changes in your HTML, or listen to Error Events on document.body during capture phase to react to errors:
<html>
<head>
<meta
http-equiv="Content-Security-Policy"
content="upgrade-insecure-requests"
/>
</head>
<body>
<script>
const el = document.createElement("img");
el.src = "http://unsafeimg";
document.body.appendChild(el);
document.body.addEventListener(
"error",
(err) => {
console.log("Failed to load\n", err.target);
},
/* Notice the true value here. It is required because Error Events do not bubble */
true
);
</script>
</body>
</html>
Another option would be to set up a Service Worker to intercept and handle insecure requests. This is probably the best solution, as this gives you full overview of what data your website it trying to load.
Sounds like you are having an issue specifically revolving around fixing mixed content policies. There are many approaches to tackle and arrive at a solution.
My recommendation is to go off some documentation provided and referenced by Google: https://web.dev - Fixing Mixed Content.
Mixed content occurs when initial HTML is loaded over a secure HTTPS connection, but other resources (such as images, videos, stylesheets, scripts) are loaded over an insecure HTTP connection. This is called mixed content because both HTTP and HTTPS content are being loaded to display the same page, and the initial request was secure over HTTPS.
First off mixed content will occur when such initial-based HTML is transferred over the network through a secure HTTPS connection. Although, the problem arises when other resources as you stated such as:
Images
Videos
Stylesheets
Scripts
...are loaded over an insecure HTTP connection. This is the definition of a mixed content issue described. It is because of an issue pertaining to assets both HTTP and HTTPS content that is being requested and loaded to display on the website of the desired origin. And the main issue is the initial request was originally sent over secure over the HTTPS protocol.
Note: Before continuing, when requesting any of these subresources overusing the insecure HTTP transfer protocol, will open up vulnerabilities of the entire origin site. Such vulnerability attacks are named on-path attacks.
Depending on the browser your website user base is primarily targeting, there are fixes and preventions to take note of being rolled out by browsers such as Google Chrome. Which will upgrade passive mixed content where it is possible. Such a process will be deciding if the resource asset is available over HTTPS, but determine if it was created to be served over the HTTP protocol, the browser will load the HTTPS version instead. So in conclusion, it will disregard the HTTP resource.
Content Security Policy (CSP)
You need to reference the below section of https://web.dev - Fixing Mixed Content linked here. It will allow you to utilize a browser-based implementation that may be used to solve and manage mixed content issues. Which allows and opens up opportunities for different enforcement policies to be implemented.
To enable CSP, you have the opportunity to set up your site to return the Content-Security-Policy HTTP header. Which has replaced the X-Content-Security-Policy older policy.
My suggestion is to make use of the <meta> HTML element. This will allow you to customize which domains you trust in regards to CSP in general and implement different customizations using this element.
This is an example where you do wish to allow any resource content from a trusted domain, and you may use alternative formatting to allow sub-domains and other aspects to grant desired outcomes. Notice the formatting, following the subdomain setting.
Content-Security-Policy: default-src 'self' example_trusted.com *.example_trusted.com
So when utilizing this, you may take an approach for certain resources such as advertisements or images you decide to trust, but must be set up appropriately.
One vague example might be, without an asterick:
content="default-src 'self' https://example.com http://example.com:80/images/"
This concludes a result conclusive of:
https://example.com # Correct
http://example.com/images/ # (Missing) Incorrect Port
http://example.com:80/images/image.jpg - Correct Port
https://example.com:81 # (Missing) Incorrect Port
You may use approaches like these referenced here at Mozilla - Content-Security-Policy, which may help form a solution.
Or just go completely vulnerable.
content="default-src * 'unsafe-inline' 'unsafe-eval'"
Many references on StackOverflow such as How does Content Security Policy (CSP) work?, which was referenced in this post. Hope I was of some help.
Complete References List:
https://web.dev/fixing-mixed-content/
https://web.dev/fixing-mixed-content/#content-security-policy
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
How does Content Security Policy (CSP) work?
What I do whenever dealing with mixed content is updating the .htaccess file with the following:
Header always set Content-Security-Policy: upgrade-insecure-requests
That should by take care of the mixed content and make sure that you load everything trough HTTPS.
Related
I want to administratively prevent a whole class of XSS attacks by not allowing anything on my page to send XHR/XMLHttpRequest (or other?) requests to other domains than the domain hosting the page. Is that possible?
I thought I could do that with Cross-Origin Resource Sharing (CORS), but it seems I was wrong. If a page hosted on domain-a.com tries to make an XHR request to domain-b.com, CORS can be used on domain-b.com pages to control whether or not that is allowed.
So if something on the page at domain-a.com tries to make an XHR request to hackers-r-us.com that will be allowed, as long as hackers-r-us.com sets the appropriate CORS headers.
But is there anything I can set on the page on domain-a.com to disallow requests to other domains such as hackers-r-us.com regardless of CORS headers on hackers-r-us.com?
To prevent requests to another domain, use CSP — specifically, the connect-src CSP directive.
CSP directives are specified using the Content-Security-Policy HTTP header, and enforced by browsers. The simplest example of a header that specifies a connect-src directive is:
Content-Security-Policy: connect-src 'self';
If you serve a document at https://example.com/foo/ with that, browsers block any frontend code in the document from making requests to URLs at any origin other than its own ('self'); i.e., browsers restrict the allowed requests only to URLs starting with https://example.com.
https://developer.mozilla.org/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src has more details and examples.
https://w3c.github.io/webappsec-csp/#directive-connect-src is the actual spec section where the browser requirements are defined; that section also has some examples.
I'm working on a Javascript App food2fork. But I get an error when AJAX call API promise fulfilled and render the results (Recipes). But when I click one of them it moves to the next page and say
Cannot GET /47746
and give an error on the console
Refused to load the image 'http://localhost:8080/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback".
How to get rid of this kind of error?
This is because a Content Security Policy (CSP) header is set somewhere in your application.
Content Security Policy (CSP) is an added layer of security that helps
to detect and mitigate certain types of attacks, including Cross Site
Scripting (XSS) and data injection attacks./.../
A CSP compatible browser will then only execute scripts loaded in
source files received from those allowlisted domains, ignoring all
other script (including inline scripts and event-handling HTML
attributes).
As an ultimate form of protection, sites that want to never allow
scripts to be executed can opt to globally disallow script execution. [edit: hence the "default-src 'none'" policy]
More on CSP: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
You can create a CSP with online tools, like
https://report-uri.com/home/generate
https://www.cspisawesome.com
A CSP with "default-src 'none'" means that nothing can be displayed/run on your domain - you have to "whitelist" the services/content that you allow (default-src is a fallback for other resource types that do not have policies of their own, so you have it set like none, then you have to add sources that are explicitly allowed).
A policy is described using a series of policy directives, each of
which describes the policy for a certain resource type or policy area.
WHAT YOU CAN DO
In your case, you may need a policy something like:
"default-src 'none'; img-src 'self'".
I'm pretty sure though, that as you go forward you'll need more rules, so check out the sources and the online CSP generators, so you won't have a hard time.
OR you may
Remove the CSP (not advised - it's a security measure)
For development purposes, you may set Content-Security-Policy-Report-Only (this way the CSP does not stop your content to be displayed/run, but shows "what would have been done, if not set to only to report the problems". Don't forget to handle this in production environment!)
REFERENCE
CSP reference: https://content-security-policy.com
More on CSP: https://scotthelme.co.uk/content-security-policy-an-introduction/
I have a Google Chrome Extension where I catch headers for each web request and look for some information in the headers. The websites that I am considering are just special and a few, and they send a default content-security-policy in the 'meta' tag of the source. Which blocks any javascript:
<meta http-equiv="Content-Security-Policy" content="script-src 'none';" >
The websites also send me their real content-security-policy in the headers. In short, this content-security-policy in the headers should be taking effect after I have done with my information search in the headers. Because, after I find the information I am searching, I override the source and write the new content to the browser with document.write() with a content script sent from my browser extension.
First of all, I just don't understand which content-security-policy is taking effect where, because the source with a content-security-policy in meta tag doesn't care about the content-security-policy in the headers any more. The one in the meta tag is effective. Is that right?
Also, when I override the source with document.write() looks like no content-security-policy is taking effect any more. If I replace it in the 'meta' tag, the browser returns a warning in console saying that it had ignored it. The one in the headers is not taking effect at all.
When does the browser evaluate the content-security-policy and is it any possible to re-evaluate it? or using the document.write() is the problem here?
Let's consider the following scenario:
a user loads https://foo.com/index.html in one of the modern browsers which allow CORS.
index.html loads a javascript from https://bar.com/script.js via the script tag.
considering a hypothetical situation where this script.js is never cached and the content of script.js has changed.
script.js makes an XHR request to https://baz.com
https://baz.com has enabled Access-Control-Allow-Credentials: * thus this XHR made by script.js goes through.
important user information now can be passed to https://baz.com which is a security risk.
Prior to CORS, XHR calls were strictly followed same-origin policy and thus calls to https://baz.com from https://foo.com would not be permitted by the browsers.
I am wondering if there is a way for https://foo.com/index.html to specify a list of XHR permissible domain names so that the above scenario would not be possible.
Any pointer is highly appreciated.
[UPDATED]
I guess I have found the answer to my question.
Thank you for being considerate 🙏
Best!
I guess I found the answer to my question.
Using connect-src directive of the Content-Security-Policy Header https://foo.com/ can restrict the XHR, fetch calls along with WebSocket, EventSource, <a> ping to desired domains.
Content-Security-Policy: connect-src <source> <source>;
More information at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/connect-src
I once thought of deleting my question but someone else like me can be benefited.
CORS blocking is done on the server side, where the response headers are set to allow requests from certain origins or not.
If bar.com/script.js fetches data from baz.com, then baz.com should have the CORS restriction.
I want to make an XMLHttpRequest to a secure uri (https://site.com/ajaxservice/) from javascript running inside a nonsecure page (http://site.com/page.htm). I've tried all kinds of nutty stuff like iframes and dynamic script elements, so far no go. I know I am violating 'same origin policy' but there must be some way to make this work.
I will take any kind of wacky solution short of having the SSL protocol written in javascript.
That won't work by default due to the same origin policy, as you mentioned. Modern browsers are implementing CORS (Cross-Origin Resource Sharing) which you could use to get around this problem. However this will only work in Internet Explorer 8+, Firefox 3.5+, Safari 4+, and Chrome, and requires some server-side work. You may want to check out the following article for further reading on this topic:
Cross-domain Ajax with Cross-Origin Resource Sharing by Nicholas C. Zakas
You can also use JSONP as Dan Beam suggested in another answer. It requires some extra JavaScript work, and you may need to "pad" your web service response, but it's another option which works in all current browsers.
You can't circumvent cross-domain origin with XHR (well, only in Firefox 3.5 with user's permission, not a good solution). Technically, moving from port 80 (http) to 443 (https) is breaking that policy (must be same domain and port). This is the example the specification itself sites here - http://www.w3.org/Security/wiki/Same_Origin_Policy#General_Principles.
Have you looked into JSONP (http://en.wikipedia.org/wiki/JSON#JSONP) or CSSHttpRequests (http://nb.io/hacks/csshttprequest)?
JSONP is a way to add a <script> tag to a page with a pre-defined global callback across domains (as you can put the <script>s src to anywhere on the web). Example:
<script>
function globalCallback (a) { /* do stuff with a */ }
And then you insert a <script> tag to your other domain, like so:
var jsonp = document.createElement('script');
json.setAttribute('src','http://path.to/my/script');
document.body.appendChild(jsonp);
</script>
And in the source of the external script, you must call the globalCallback function with the data you want to pass to it, like this:
globalCallback({"big":{"phat":"object"}});
And you'll get the data you want after that script executes!
CSSHttpRequests is a bit more of a hack, so I've never had the need to use it, though feel free to give it a try if you don't like JSONP, :).
You said you would take anything short of having the SSL protocol written in JavaScript... but I assume you meant if you had to write it yourself.
The opensource Forge project provides a JavaScript TLS implementation, along with some Flash to handle cross-domain requests:
http://github.com/digitalbazaar/forge/blob/master/README
Check out the blog posts at the end of the README to get a more in-depth explanation of how it works.