Can I make requests from an extension without requesting <all_urls> permission? - google-chrome-extension

I am generally wary of extensions that request the <all_urls> permission.
I've had to reluctantly use it in my own extension as I couldn't find any other way to do a simple web-request without being hit by CORS restrictions.
I don't understand why these restrictions apply to extensions?
Presumably there's a good reason.
But I don't need to snoop on requests in transit - this extension is a devtools-extension, and in terms of observing requests, it gets what it needs from chrome.devtools.network API and doesn't need the <all_urls> permission for that.
I had to enable <all_urls> solely so I could make an outgoing request here.
Is there a different way to avoid the CORS restrictions for a simple outgoing web-request?
A less "drastic" permission that doesn't seem as scary to end users?

Related

Same Origin Policy easily circumvented?

I've read an article which used Cors-Anywhere to make an example url request, and it made me think about how easily the Same Origin Policy can be bypassed.
While the browser prevents you from accessing the error directly, and cancels the request altogether when it doesn't pass a preflight request, a simple node server does not need to abide to such rules, and can be used as a proxy.
All there needs to be done is to append 'https://cors-anywhere.herokuapp.com/' to the start of the requested url in the malicious script and Voila, you don't need to pass CORS.
And as sideshowbarker pointed out, it takes a couple of minutes to deploy your own Cors-Anywhere server.
Doesn't it make SOP as a security measure pretty much pointless?
The purpose of the SOP is to segregate data stored in browsers by their origin. If you got a cookie from domain1.tld (or it stored data for you in a browser store), Javascript on domain2.tld will not be able to gain access. This cannot be circumvented by any server-side component, because that component will still not have access in any way. If there was no SOP, a malicious site could just read any data stored by other websites in your browsers.
Now this is also related to CORS, as you somewhat correctly pointed out. Normally, your browser will not receive the response from a javascript request made to a different origin than the page origin it's running on. The purpose of this is that if it worked, you could gain information from sites where the user is logged in. If you send it through Cors-Anywhere though, you will not be able to send the user's session cookie for the other site, because you still don't have access, the request goes to your own server as the proxy.
Where Cors-Anywhere matters is unauthenticated APIs. Some APIs might check the origin header and only respond to their own client domain. In that case, sure, Cors-Anywhere can add or change CORS headers so that you can query it from your own hosted client. But the purpose of SOP is not to prevent this, and even in this case, it would be a lot easier for the API owner to blacklist or throttle your requests, because they are all proxied by your server.
So in short, SOP and CORS are not access control mechanisms in the sense I think you meant. Their purpose is to prevent and/or securely allow cross-origin requests to certain resources, but they are not meant to for example prevent server-side components from making any request, or for example to try and authenticate your client javascript itself (which is not technically possible).

Security concerns when changing permissions in Chrome Extentions

I'm working on an extension that's basically sending out an XHR request and parsing/displaying incoming XML. Ideally I'd like to let users enter the URL they want to send the request to, but to do this I believe I need to change the URL specified in the manifest.json every time the user enters a new URL. Are there any security concerns I should be aware of if implemented? If not I figure just setting the permission to *://*/* might be easier.
If you are letting the user select a URL, you have 2 approaches.
Just allow "<all_urls>" in the manifest (slightly stronger than "*://*/*"). Unless you're doing something specifically bad (like eval or exposing your internals using web_accessible_resources), the only security risk is yourself.
A fancy approach would be to use optional permissions. You put "<all_urls>" in optional permissions then request permissions for new hosts at runtime.
Pros: No scary dialog on install; give the power users comfort in knowing they provided only granular access.
Cons: A permission dialog will appear every time you need new permissions.

Should I expect any issues if I want to communicate between a secure (https) Website and a chrome extension?

I have a chrome extension that currently communicates with a website over http, what would be the difficulties/problems that could occur if I switch my website to be https.
Communication is done using this method (chrome.runtime.sendMessage)
https://developer.chrome.com/extensions/messaging#external-webpage
And I also pull some Iframe pages from the website
As far as chrome.runtime messaging goes, Chrome does not care, as long as you have permissions.
And that might be your problem if you specified your match patterns as "http://example.com/*" instead of "*://example.com/*". Adding a permission for HTTPS if it wasn't there before may trigger a new permission warning, which is.. unpleasant.
Triggering a new permission warning for an already-deployed extension means that the extension is automatically disabled after the update.
The user is then presented with a popup explaining that the extension was disabled due to requesting more permissions that it had, and requesting the user to review them (or leave the extension disabled). You run the risk of users deciding not to bother, or misunderstand this warning and think it's malware / complain.
Fortunately, "externally_connectable" match patterns do not trigger warnings - because such connections always have to be initiated by the page. If, however, you are also using a permission to do XHR, or a match pattern to inject a content script - the above applies.
You could potentially employ optional permissions to avoid this scenario, but that's a complicated way.

Is CSRF possible with PUT or DELETE methods?

Is CSRF possible with PUT or DELETE methods? Or does the use of PUT or DELETE prevent CSRF?
Great question!
In a perfect world, I can't think of a way to perform a CSRF attack.
You cannot make PUT or DELETE requests using HTML forms.
Images, Script tags, CSS Links etc all send GET requests to the server.
XmlHttpRequest and browser plugins such as Flash/Silverlight/Applets will block cross-domain requests.
So, in general, it shouldn't be possible to make a CSRF attack to a resource that supports PUT/DELETE verbs.
That said, the world isn't perfect. There may be several ways in which such an attack can be made possible :
Web Frameworks such as Rails have support for "pseudo method". If you put a hidden field called _method, set its value to PUT or DELETE, and then submit a GET or POST request, it will override the HTTP Verb. This is a way to support PUT or DELETE from browser forms. If you are using such a framework, you will have to protect yourself from CSRF using standard techniques
You may accidentally setup a lax response headers for CORS on your server. This would allow arbitrary websites to make PUT and DELETE requests.
At some point, HTML5 had planned to include support for PUT and DELETE in HTML Forms. But later, they removed that support. There is no guarantee that it won't be added later. Some browsers may actually have support for these verbs, and that can work against you.
There may just be a bug in some browser plugin that could allow the attacker to make PUT/DELETE requests.
In short, I would recommend protecting your resources even if they only support PUT and DELETE methods.
Yes, CSRF is possible with the PUT and DELETE methods, but only with CORS enabled with an unrestrictive policy.
I disagree with Sripathi Krishnan's answer:
XmlHttpRequest and browser plugins such as Flash/Silverlight/Applets
will block cross-domain requests
Nothing stops the browser from making a cross-domain request. The Same Origin Policy does not prevent a request from being made - all it does is prevent the request from being read by the browser.
If the server is not opting into CORS, this will cause a preflight request to be made. This is the mechanism that will prevent a PUT or DELETE from being used, because it is not a simple request (the method needs to be HEAD, GET or POST). Assuming a properly locked down CORS policy of course (or none at all which is secure by default).
No. Relying on an HTTP verb is not a way to prevent a CSRF attack. It's all in how your site is created. You can use PUTs as POSTs and DELETEs as GETs - it doesn't really matter.
To prevent CSRF, take some of the steps outlined here:
Web sites have various CSRF countermeasures available:
Requiring a secret, user-specific token in all form submissions and side-effect URLs prevents CSRF; the attacker's site cannot put the
right token in its submissions1
Requiring the client to provide authentication data in the same HTTP Request used to perform any operation with security
implications (money transfer, etc.)
Limiting the lifetime of session cookies Checking the HTTP Referer header or(and)
Checking the HTTP Origin header[16]
Ensuring that there is no clientaccesspolicy.xml file granting unintended access to Silverlight controls[17]
Ensuring that there is no crossdomain.xml file granting unintended access to Flash movies[18]
Verifying that the request's header contains a X-Requested-With. Used by Ruby on Rails (before v2.0) and Django (before v1.2.5).
This protection has been proven unsecure[19] under a combination of
browser plugins and redirects which can allow an attacker to
provide custom HTTP headers on a request to any website, hence
allow a forged request.
In theory it should not be possible as there is no way to initiate a cross-domain PUT or DELETE request (except for CORS, but that needs a preflight request and thus the target site's cooperation). In practice I would not rely on that - many systems have been bitten by e.g. assuming that a CSRF file upload attack was not possible (it should not be, but certain browser bugs made it possible).
CSRF is indeed possible with PUT and DELETE depending on the configuration of your server.
The easiest way to think about CSRF is to think of having two tabs open in your browser, one open to your application with your user authenticated, and the other tab open to a malicious website.
If the malicious website makes a javascript request to your application, the browser will send the standard cookies with the request, thus allowing the malicious website to 'forge' the request using the already authenticated session. That website can do any type of request that it wants to, including GET, PUT, POST, DELETE, etc.
The standard way to defend against CSFR is to send something along with the request that the malicious website cannot know. This can be as simple as the contents of one of the cookies. While the request from the malicious site will have the cookies sent with it, it cannot actually access the cookies because it is being served by a different domain and browser security prevents it from accessing the cookies for another domain.
Call the cookie content a 'token'. You can send the token along with requests, and on the server, make sure the 'token' has been correctly provided before proceeding with the request.
The next question is how do you send that value with all the different requests, with DELETE specifically difficult since it is not designed to have any kind of payload. In my opinion, the cleanest way is to specify a request header with the token. Something like this x-security-token = token. That way, you can look at the headers of incoming requests, and reject any that are missing the token.
In the past, standard ajax security restricted what could be done via ajax on the malicious server, however, now-a-days, the vulnerability depends on how you have your server set up with regards to accees-control configurations. Some people open up their server to make it easier to make cross domain calls or for users to make their own RESTful clients or the like, but that also makes it easier for a malicious site to take advantage unless CSRF prevention methods like the ones above are put in place.

how secure is an iframe

I'm in the process of making a portal website and I wanted to include an iframe which would route people to an intranet. Is there any downsides to this as far as security is concerned?
I think that maybe there's a misunderstanding on your side regarding the function of IFrames: An <iframe> will not route anything. It just tells the user's browser which URL to fetch and show inside it. This means that
People need access to the intranet to actually load the contents of the <iframe>, which might not be what you expected.
It's not a security risk per se.
It is no more or less secure than giving those people direct web access to that intranet.
If you really want to know whether something is "secure" or not, you need to specify the types of threat that you need to protect against, what your tolerance is for breaks in that security, and what additional mechanisms that you have taken to secure your site (for example password authentication, NTLM, SSL, etc).

Resources