Is there any way of storing data (for example, a CSRF token) that cannot be accessed by a Chrome extension under any circumstances?
Ideally I would like to store information that would remain secure even if a naïve user granted all permissions to an extension.
I was wondering if there was somewhere that was accessible to the page but inaccessible to an extension.
Consider the so-called page-level scripts. A content script can inject a <script> tag into the page, and it will be executed in the same environment as the page.
It can then extract your hypothetical secure data and communicate with the rest of the extension.
What's worse, you can't reasonably prevent this injection, as it ignores your page's CSP.
Related
There are already a few questions related to using the local storage with iframes to be able to share data across different domains. However, none of them addresses the issue when the "Block third-party cookies" is enabled.
Currently, by default now Chrome uses the option "Block third-party cookies in Incognito" which breaks the localStorage use within iframes whenever you use the incognito mode.
Is there any workaround for this problem? We're using post message to send the data for the iframe.
The behavior you are describing sounds exactly like the pattern of behavior the Third-Party Cookie Block is intended to prevent.
There have been numerous changes in Chrome (and other browsers) regarding cookies and iframe.
The basics of what is changing is there is now a 'SameSite' cookie policy, where Only cookies set as SameSite=None; Secure will be available in third-party contexts, provided they are being accessed from secure connections.
Also in safari, the third-party frame will have to request access to the storage API before the cookie will be accessible.
Firefox is using a partitioned approach to the storage, and so the frame will behave as normal unless you then open your application as a new window then the cookie store may or may not follow depending on how the new window was created.
Cookie Status is an excellent resource to track how third party cookies work in the different browsers and what you should change to make it work.
I want to add my two cents here because all replies to this question completely miss the point of what's being asked. Take what I have here with a grain of salt, it's based on the most recent versions of Chromium and my personal experience, but maybe it can help someone understand the mess Chromimium has made.
Obscure Chromium Setting
First and foremost the setting within Chromium applications does not explicitly state that local storage or anything regarding "data" will be impacted by "blocking third-party cookies".
Ironically this setting used to actually explain that third-party cookies and data would be blocked, but in recent versions no longer mention data anymore, just cookies.
Is local storage a Cookie?
No. Local storage has nothing to do with cookies, and therefore the option for "blocking third-party cookies" is disingenuous because it lacks describing that local storage will also be blocked.
Local Storage data is stored by the browser for a particular domain. This data is not shared or exposed in any way.
So does local storage have "third-party data"?
No, there is also nothing "third-party" about local storage.
In context of cookies, a "third-party cookie" is a cookie for a domain that was created by a different domain, hence being "third-party". This allows domains to inject data into cookies that get sent to a different domain, which could be useful if you want to let that other domain know something, though this could also become nefarious. This essentially was a way of two domains to have a communication channel based on the user's session, but it becomes a privacy concern because it enables these domains to communicate in context of the user.
What does "third-party" mean for local storage? Nothing. Local storage is bound to the domain that's accessing the storage object - there is no "third-party" mechanism when setting or retrieving data from local storage since it is always in context of the window frame where the code is executing.
This further exasperates the problem: Why does "blocking third-party cookies" prevent local storage which is neither "third-party" nor a "cookie"?
So what does this setting do to local storage?
The "block third-party cookies" setting will block, as the name suggests, third-party cookies, but will also block local storage within an embedded iframe document. The embedded page will not be able to access the local storage property and will throw "Access denied" exceptions when the web page attempts to do so.
Blocking third-party cookies will have no impact to websites since it's used as a mechanism to share information with no returned output and no dependency of success. If your app uses local storage, it will likely break without it.
What's the security concern?
Doesn't that make sense that an embedded page can't access the local storage?
As other comments have incorrectly stated is that accessing the local storage within an embedded iframe would essentially enable cross-domain data access.
This is incorrect. The localStorage property is unique to the window variable of the frame, it is not unique to the parent domain. In other words, if you have an embedded iframe it will have a separate local storage than the parent window. This is because local storage is unique to the domain for which the code is executing in, and therefore there is no "cross-domain" access happening as part of it.
There must be other ways this is a security concern
As other comments have mentioned, the ultimate concern is leaking data across domains. So how can this happen?
It is technically possible to access the local storage property bi-laterally - child iframes can access their parent's window property and vice-versa, parent frames can access embedded iframe window objects, however Chromium blocks this by default. I tried turning off all security settings within Chromium and could not directly access the localStorage property in a parent/child or child/parent direction.
In the context of Chromium I have no reason to believe that local storage can be accessed across domains in any way unless it's explicitly instructed by the frame source page using a special header.
So why does Chromium block local storage in iframes?
Perhaps it made sense at a time before local storage became what it is today, or before accessing iframe window properties from relative frames was prevented.
Ultimately if Chromium implements local storage properly, there should be no possibility of cross-domain access without the hosting website being explicitly configured to allow such behavior. See FireFox for an example of this done properly.
What should Chromium do?
Separate out blocking local storage into it's own setting, and it should be disabled by default because there is very little reason to outright disable the entire feature that breaks a website.
I need to incorporate in my web application some content from an external dynamic web page on which I have no control.
Then I need to filter some of the content of this page or to hide it for presenting only the relevant part that is interesting for my use.
I need also that the scripts on the external page are still working on the source site of the loaded content without cross-site protection.
Is all that possible? How can I do it? Any code example, please?
I suppose that this can be made with JS on client side .
I work on back side and these themes are quite extraneous to me, please don't blame me.
No, it is not possible.
Browser same-origin policy is designed to prevent malicious websites from doing evil.
Same-origin Policy restricts JavaScript network access to prevent evil.
Same-origin Policy also restricts script API Access to prevent evil.
From the Docs:
JavaScript APIs like iframe.contentWindow, window.parent, window.open, and window.opener allow documents to directly reference each other. When two documents do not have the same origin, these references provide very limited access to Window and Location objects.
To communicate between documents from different origins, use window.postMessage.
— MDN Web Security Reference - Cross-origin script API access
One can not use <iframe> elements as a way to "avoid cross site problems". The Same Origin Policy was created to protect users from evil web pages.
I know by default the HTML page on other domains can't access my images, videos. They can only show them. But sadly, they can still run my scripts. If my script exposes some variables to the global scope, then the internal logic may be known by others.
I have a private website that others can't visit. Only I can visit it by sending a token in the Cookie to the server. If the token isn't included in the Cookie, every request will cause a 500 server error response. This is secure because everything is on HTTPS.
But unfortunately, I find this isn't very safe on my own machine, because after I visit my site and then visit a malicious site, this malicious site can use the following method to run my script:
<script src="https://my-website.com/main.js"></script>
That's because the Cookies of my website on my machine will be sent to my server as 3rd-party Cookies.
How to prevent that? Can access-control-allow-origin do so?
P.S. I don't want to disable all 3rd-party cookies in browser settings. Cookie's SameSite also doesn't make sense because only Chrome support it now.
There are a number of imaginable ways to prevent other sites from using the script element to run copies of scripts from your site in their sites, but CORS isn’t one of them.
Browsers are where the same-origin policy (SOP) is enforced and browsers are what block JavaScript running in Web apps from being able to use responses from cross-origin requests.
But browsers don’t use SOP/CORS when a Web app uses the script element to embed some JavaScript. Specifically, browsers don’t check that the script is served from the other site with an Access-Control-Allow-Origin header, which is the foundation of the whole CORS protocol.
So CORS is definitely not a solution to the problem you seem to want to solve.
But unfortunately, I find this isn't very safe on my own machine, because after I visit my site and then visit a malicious site, this malicious site can use the following method to run my script:
<script src="https://my-website.com/main.js"></script>
But if that site embeds your script in theirs that way, it runs within their origin, not yours. It runs there as a trusted script with all the same privileges of any script they’ve written themselves.
In that scenario, the other site is the one taking a security risk—because you can at any time change your https://my-website.com/main.js script to do anything you want at their site.
That is, by embedding your script that way, the other site gives your script programmatic fully-trusted access to do anything it wants at their entire origin—gifting you an XSS opportunity.
I'm developing a Chrome extension and I need to store some data and then get it in some point. I did investigation on available storages and came across to the following ones: window.localStorage and chrome.storage.local.
So my question is, which one is the right choice to use in Chrome extensions:
window.localStorage or chrome.storage.local?
P.S. I'm using browser action to load a local HTML in IFRAME. So I'm not using popup.js.
localStorage
Pros:
Synchronous, and thus easier to work with: var value = localStorage[key]
Has support in Dev Tools: Resources > Local Storage to view and modify.
Cons:
Only stores strings, therefore you need to serialize data yourself, i.e. with JSON.stringify
Is not accessible from content scripts (or rather, context scripts share it with the page and not the extension), so you need to rely on Messaging to pass values to them.
Synchronous AND shared between concurrently-executing extension pages, leading to possible synchronization issues.
chrome.storage.local
Pros:
Automagically serializes JSON-compatible data, can store non-strings with no additional boilerplate.
Fully available within Content Scripts.
Supports events that notify about changes: chrome.storage.onChanged
With "unlimitedStorage" permission, can hold arbitrarily large amounts of data.
Has a nice built-in mechanism for default values:
chrome.storage.local.get({key: defaultValue}, function(value){/*...*/});
Fully supported in Firefox WebExtensions and Edge Extensions.
Cons:
Asynchronous, therefore a bit harder to work with:
chrome.storage.local.get("key", function(value){/* Continue here */});
Not visualized in Dev Tools; one needs to call chrome.storage.local.get(null) to get all values or use something like Storage Area Explorer.
chrome.storage.sync
Same as above, but:
Pros:
Automatically synced between signed-in Chrome instances, if extensions sync is enabled.
Cons:
Inflexible quotas on data size and update frequency.
As of 2016-11-06, not yet supported in either Firefox WebExtensions or Edge Extensions, so non-portable.
Note: storage.sync is now FF WebExtension compatible, though there is no way to make Chrome and FF natively sync between each other.
It depends entirely on what your Chrome Extension will be doing. window.localStorage is HTML5 storage. Unless you're running it in the background page, it can only allow you to get and set data into storage for a specific domain. This is also true for code injected into the DOM, since it would use the localStorage on the web page.
In other words, you won't be able to share data across different web pages unless you use localStorage in the background page, which operates independently of web pages, since it has a chrome:// URI as its domain.
chrome.storage.local, on the other hand, is designed for Chrome Extensions and Chrome Apps to store data in a more central location. Since this isn't accessible to normal web pages, each Extension gets its own storage. One possibility is for your background page to handle dealing with the setting and getting of the data, while your content scripts deal with modifying and interacting with the web page.
However, these API's work in content scripts as well, and both of the extensions I've written use chrome.storage.local called from the content scripts.
As an example, I built a Stack App that preserves inbox items in Stack Exchange until you've actually read them, called StackInbox. Since Stack Exchange sites span across hundreds of domains, I chose chrome.storage.local because I could save the user's accountId and reuse it across all the sites, ensuring that the inbox data is synchronized, while also using this directly in the content script.
As a simple test, put some data in localStorage on one domain, in a content script, and try to pull it from another, and you'll see that the data won't be there. With chrome.storage.local, this isn't a problem.
Lastly, Chrome Extensions and Chrome Apps are whitelisted, since the user chose to install it, so they typically can do more things than a normal website. For instance, by specifying the "unlimitedStorage" permission in your manifest, you can store data well beyond the 5MB limit placed upon HTML5 localStorage.
For more information, see Google's documentation on Chrome Storage.
I'm doing an extension now and i have one part of script which is static (will never change) and another part which is loaded from the website. And, i'm seeing 2 ways:
To load it with XMLHttpRequest and inject into web page
To put it as a <script src="example.com/myscript.js"></script> and have it load it itself
But, the second way probably won't have access to my extension API (to functions defined in extension files, i.e. in chrome://myext/script.js)
And, the first way will probably be unsecure because i will have to eval the code in a gBrowser.contentWindow.wrappedJSObject object which is a Window object for the loaded page
Any ideas?
Are you saying that you want the dynamic script to have chrome privileges? If so, why not load it using XMLHttpRequest, save it to disk and then import it as a JavaScript Module (https://developer.mozilla.org/en/JavaScript_code_modules/Using). Obviously there are security considerations since you are giving a script from the web pretty much unlimited privileged, but if you control the script's source then you are presumably okay. If you are really worried you can use HTTPS to download the script, which will protect against someone intercepting the traffic.
If you want the code to run with content privileges but have access to functions in your chrome JavaScript, then maybe you want to expose the chrome functions to content as described in this article: http://weblogs.mozillazine.org/weirdal/archives/017188.html