When I inspect a website,
I see the cssRules from document.styleSheets[x].cssRules
However, with this website stackoverflow.com, when I inspect with Chrome browser, I see document.styleSheets, but cssRules is null.
How come this is possible?
That's because the style sheets are coming from a different domain. Some browsers (such as Chrome) implement strict cross-domain policies by throwing security errors or setting the cssRules and ownerRule to null when it comes from a different domain...in your case the style sheets come from a CDN
MDN quotes the following in the CSSStyleSheet documentation...
In some browsers, if a stylesheet is loaded from a different domain,
calling cssRules results in SecurityError.
https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet
To try bypass this problem, you can add crossorigin="anonymous" in the link tag to prevent the error.
More info here:
https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/crossorigin
This will create a potencial cors request but the server must respond with Access-Control-Allow-Origin: * or Access-Control-Allow-Origin: <authorized-domain>.
You can check here to see how to add CORS support to your server.
For more information about CORS you can read this and this.
Related
OWASP recommends to use Content-Security-Policy: frame-ancestors 'none' in API responses in order to avoid drag-and-drop style clickjacking attacks.
However, the CSP spec seems to indicate that after the HTML page is loaded any other CSP rules in the same context would be discarded without effect. Which makes sense in my mental model of how CSP works but if OWASP recommends it then I'm sure missing something.
Can anyone explain how can a CSP header in a XHR request improve security, after the fact that the HTML page is already loaded and the "main" CSP already evaluated? How that works in the browser?
how can a CSP header in a XHR request improve security, after the fact that the HTML page is already loaded and the "main" CSP already evaluated?
You are right, browsers use CSP from main page and just ignore the CSP header sent along with the XHR requests.
But you haven't considered the second scenario - the API response is open in the browser's address bar or in a frame. In this case, cookies will be available to the response page, and if XSS is detected in the API (as, for example, in the PyPI simple endpoint API), then the user's confidential data may be available to an attacker.
Therefore, it is better to protect API responses with the "default-src `none" policy, as well as 404/403/500, etc pages.
Can anyone explain how can a CSP header in a XHR request improve security, after the fact that the HTML page is already loaded and the "main" CSP already evaluated? How that works in the browser?
Adding to the correct answer by granty above, Frames are commonly used for CSP bypasses.
If a frame was allowed in a page (not blocked by the CSP), the frame has it's own CSP scope. So if you create some API for data - you don't want to allow it to be set as a frame as it could be used for bypassing the original CSP (for data exfiltration as an example).
So you can block this vulnerability by setting Content-Security-Policy: frame-ancestors 'none';, and then your API will refuse to be framed.
See this article on bypassing CSP for more info. The POC uses a creative hack:
frame=document.createElement(“iframe”);
frame.src=”/%2e%2e%2f”;
document.body.appendChild(frame);
which in turn triggers the NGINX error code page that does not have any CSP set. Many production CSPs are vulnerable to this issue.
Since not setting a CSP on a framed page would essentially default to no CSP (everything is open), the article suggests:
CSP headers should be present on all the pages, event on the error pages returned by the web-server
The frame-ancestors 'none' directive will indicate to the browser on page load that it should not be rendered in a frame (including frame, iframe, embed, object, and applet tags). In other words the policy does not allow it to be framed by any other pages.
The CSP header for the API or page is read at load. It is not something that happens after the fact. The "main" CSP isn't pertinent because it's the URI in the frame that's sending the CSP for itself over. The browser simply honors the frame-ancestor 'none' request by that URI
The frame-ancestors directive restricts the URLs which can embed the resource using frame, iframe, object, or embed. Resources can use this directive to avoid many UI Redressing [UISECURITY] attacks, by avoiding the risk of being embedded into potentially hostile contexts.
References
CSP frame-ancestors
Clickjacking Defense Cheat Sheet
Content Security Policy
Web Sec Directive Frame Ancestors
Chrome update has given me great trouble
So far, I still haven't found anyone's answer in Chrome 80 that correctly answers SameSite issuess.
Leave the following questions for me and us.
In my html page, there is only provided by YouTube.
However, in Chrome, 'cross-site requests if they are set with SameSite = None and Secure' are displayed.
What should I do?
I only did YouTube iframe, what value should I send cookie value and session value?
I want a direct solution.
A fake method like 'cross-site-cookie = name' doesn't help me.
I need a direct way to experience.
I want about php version <7.3 and I want to solve the problem with php or javascript or .htaccess etc.
only youtube iframe tag
Chrome's new cookie policy requires applications to be served over HTTPS, if some iframe content involves usage of secure cookies.
This rule is enforced to disable unsafe requests accross sites, and reduce the risk of Cross Site Request Forgery (CSRF).
You can read more about possible use cases in this post:
https://web.dev/samesite-cookie-recipes/
When trying to use a font file from another domain on a web page, I ran into the restrictions of the Cross Origin Resource Policy in all its glory.
So, instead of referencing the external font URL directly from CSS with #font-face, I referenced a local URL path which redirects to the external font resource. I thought the browser might treat the font as a same-domain resource. And indeed, the redirect seemed to fool Chrome into using the external font, but this was not the case with Firefox, which did not allow it.
My question is, which of the two behaviors, demonstrated by Chrome and Firefox respectively, is the standards-compliant one?
From: http://www.w3.org/TR/cors/#cors-api-specification-redirect
Since browsers are based on a same origin security model and the
policy outlined in this specification is intended for APIs used in
browsers, it is expected that APIs that will utilize this policy will
have to handle a same origin request that results in a redirect that
is cross-origin in a special way.
For APIs that transparently handle redirects CORS API specifications are encouraged to handle this scenario transparently as well by "catching" the redirect and invoking the cross-origin request algorithm on the (cross-origin) redirect URL.
From what I can understand, it seems that Firefox handles it 'the right way'.
I am developing a web page that needs to display, in an iframe, a report served by another company's SharePoint server. They are fine with this.
The page we're trying to render in the iframe is giving us X-Frame-Options: SAMEORIGIN which causes the browser (at least IE8) to refuse to render the content in a frame.
First, is this something they can control or is it something SharePoint just does by default? If I ask them to turn this off, could they even do it?
Second, can I do something to tell the browser to ignore this http header and just render the frame?
If the 2nd company is happy for you to access their content in an IFrame then they need to take the restriction off - they can do this fairly easily in the IIS config.
There's nothing you can do to circumvent it and anything that does work should get patched quickly in a security hotfix. You can't tell the browser to just render the frame if the source content header says not allowed in frames. That would make it easier for session hijacking.
If the content is GET only you don't post data back then you could get the page server side and proxy the content without the header, but then any post back should get invalidated.
UPDATE: 2019-12-30
It seem that this tool is no longer working! [Request for update!]
UPDATE 2019-01-06: You can bypass X-Frame-Options in an <iframe> using my X-Frame-Bypass Web Component. It extends the IFrame element by using multiple CORS proxies and it was tested in the latest Firefox and Chrome.
You can use it as follows:
(Optional) Include the Custom Elements with Built-in Extends polyfill for Safari:
<script src="https://unpkg.com/#ungap/custom-elements-builtin"></script>
Include the X-Frame-Bypass JS module:
<script type="module" src="x-frame-bypass.js"></script>
Insert the X-Frame-Bypass Custom Element:
<iframe is="x-frame-bypass" src="https://example.org/"></iframe>
The X-Frame-Options header is a security feature enforced at the browser level.
If you have control over your user base (IT dept for corp app), you could try something like a greasemonkey script (if you can a) deploy greasemonkey across everyone and b) deploy your script in a shared way)...
Alternatively, you can proxy their result. Create an endpoint on your server, and have that endpoint open a connection to the target endpoint, and simply funnel traffic backwards.
Yes Fiddler is an option for me:
Open Fiddler menu > Rules > Customize Rules (this effectively edits CustomRules.js).
Find the function OnBeforeResponse
Add the following lines:
oSession.oResponse.headers.Remove("X-Frame-Options");
oSession.oResponse.headers.Add("Access-Control-Allow-Origin", "*");
Remember to save the script!
As for second question - you can use Fiddler filters to set response X-Frame-Options header manually to something like ALLOW-FROM *. But, of course, this trick will work only for you - other users still won't be able to see iframe content(if they not do the same).
I just did an audit of one of my web application page (built using ASP.Net and running on development server) using Google chrome's developer tool. One particular warning caught my eyes:
Serve static content from a cookieless domain (5)!
I would like to know is it possible to avoid cookies for these kind of requests. I see that there is no cookie requests for javascript files as well. I it possible to avoid cookies in the header for these files as well? and why didn't the browser attach cookies for javascript files and attach for CSS and image?
Cookie are "attached" to a domain and a path. If you set cookies for a path above your files, they'll be sent with any request for those files.
The warning message itself tells you how to fix this - use another domain for your static content. Or a subdomain, as long as you make sure you keep your main domain cookieless in that case.
The easiest thing to do is to follow the exact suggestion in the warning message you pasted in (serve your static assets from a completely different hostname on which you don't set cookies). But in modern browsers you now also have the option of setting the crossorigin="anonymous" attribute on the relevant elements, which will prevent cookies from being sent for the matching requests. You will need to combine this with returning an access-control-allow-origin: YOUR-ORIGIN-HERE.com header in your static asset responses.