We are currently deploying an MVC app that needs to also support a number of clients that have cookies blocked due to corporate policy. We have cookieless sessions and authentications set to autodetect because we figured out that cookieless="UseDeviceProfile" is completely unreliable since we have to support multiple browsers and Chrome (as well as IE9) craps out with this setting (UseDeviceProfile). Everything works great with the setting "AutoDetect" except for one instance:
If the user is blocking cookies and types in http://somehost.com ASP.Net adds ?AspAutoDetectCookieSupport=1 to the end of the string leaving you with a url of http://somehost.com?AspAutoDetectCookieSupport=1. When this string comes into our MVC app it blows up with a 404 error. However, if you append a "/" to the end of the initial url, as in
http://somehost.com/, then everything works as expected and ASP.Net prepends the url with the session string (eg http://somehost.com/(sessionstring)/......
This will be somewhat of an edge case since the vast majority of the users will be hitting the app from a url we send to them which is not susceptible to this "bug". Additionally, the vast majority of the users will have cookies enabled as well. But we would still not like having even the small number of users this would affect see this ugly error.
Any suggestions?
Related
I am currently trying to host a website as an experiment on Heroku, I deployed the back end which you can consider yyyy.herokuapp.com and the front end with you can consider xxxx.herokuapp.com,
Now, here's the issue, I need to set cookies between xxxx and yyyy, I know this will be a massive security issue but since this is an experimental website I am not willing to get a custom domain, I tried to set the cookies' domain to: herokuapp.com, .herokuapp.com, *.herokuapp.com, xxxx.herokuapp.com, yyyy.herokuapp.com.
Yet it doesn't work, chrome denies the cookies and gives this message:
This attempt to set a cookie via a Set-Cookie header was blocked because its Domain attribute was invalid with regards to the current host url.
So, how do I approach this issue without the need for a custom domain?
this is my configuration to set cookies (on the back end which uses flask)
response.set_cookie("example_cookie", value="cookie value",
max_age=900, expires=datetime.datetime.utcnow() +
datetime.timedelta(seconds=900), secure=True, domain=".herokuapp.com",
samesite='none')
If herokuapp.com were not a public suffix (a.k.a. an effective top-level domain or eTLD), then in the case of a cookie set by xxxx.herokuapp.com with Domain=herokuapp.com, browsers would send that cookie to yyyy.herokuapp.com
However, there is a snag: in order to isolate its different tenants, Heroku required herokuapp.com be added to the public-suffix list a while back. Most browsers refuse to set a cookie for a public suffix:
For security reasons, many user agents are configured to reject Domain attributes that correspond to “public suffixes”. For example, some user agents will reject Domain attributes of “com” or “co.uk”.
Therefore, attempts to set a cookie with Domain=herokuapp.com will be rejected by browsers, as you've experienced.
Note: adding a leading dot in the Domain attribute of the Set-Cookie HTTP header has no effect, at least in modern browsers.
To get out of this difficulty, you could simply buy a cheap domain name (say infinityvive.com) to serve both your frontend and backend from subdomains of it. Then you'd be able to use Domain=infinityvive.com because your domain would not be a public suffix.
I have a single-page static app hosted at example.com. My server for the app is hosted at server.com. I keep these two services completely separate and they can scale differently this way. When the user wants to login their username and password is passed to yoyoma.com and a cookie is set on server.com with the access_token. The user is then redirected to example.com and is now logged in.
From the static app at example.com, we can now make AJAX requests to server.com setting withCredentials=true so that the access_token we set is passed along to server.com. This works perfectly in every browser but Safari. The only way I've gotten Safari to work is by going to preferences -> privacy -> disabling "Prevent cross-site tracking". I know that the cookies are getting set on server.com, but they don't get passed with the AJAX request. It seems to be some Privacy feature that Apple thinks is just wonderful, but how are you supposed to get around this issue. I'm not an ad service, I'm not doing anything evil, just trying to get my app to work. I specifically want to build a single page app where the server is on a different domain. Is this possible in Safari or has their privacy setting made this impossible?
Note: I should also mention to security fanatics that when the access_token cookie is set, the user is then redirected to example.com with a CSRF token. This csrf token is passed in every AJAX request by a header to prevent Cross Site Request Forgery.
Assuming you're set on keeping different domains - which is not at all unreasonable there are some ways to tackle it, but they come with compromises
1
Have example.com redirect to a server rendered server.com/login for creating the httpOnly cookie and then redirect them back to their logged in state in your SPA.
As I understand it, when Prevent cross-site tracking is enabled in Safari, the intention is to have the user interact with the other domain before cookies are allowed to be sent.
By redirecting them, that intent has been created and you should have no issue setting a cookie and have it be sent by example.com.
However it does come it its own set of limitations
Read more
2
Look into the discussion related to StorageAccess as the idea here is to work with third party auth solutions that rely on cookies from different domains. Safari ITP has sorta made those harder to use, so the idea is to work with vendors for a better solution than LocalStorage.
3
Store your key in LocalStorage, and vet all running javascript code coming from you and make sure to follow best practices when it comes to dealing with user created values.
LocalStorage exposes your to potential XSS, but Cookies expose you to CSRF attacks. You have to mitigate those and it's not too hard, but keep in mind you introduced those vectors when cookies were used.
Any XSS that happens is game over, even with httpOnly cookies. Forget your auth key, running the attackers code can do so much more damage.
Keylogger to take username/password
If the attack happens after an authed state, they could pop up a modal asking re-auth.
Submit a request to change email and then ask for password reset
Don't get me wrong, it's easier to dump LocalStorage as a generic attack versus the attacks listed above
That being said, in the end the resources you spend on dealing with cookie issues, could be better spent hardening down your javascript running on the users browsers to ensure they aren't running malicious code
You can't protect them from extensions though, and a httpOnly cookie would at the very least ensure that their keys aren't leaked. Know your compromises.
Edit: Keep in mind that whatever approach you're taking, any further reliance on browser needs to think through the different versions of browsers out in the wild. As an example, don't assume using httpOnly cookies and setting a sameSite policy negates the need for a CSRF token. Any addition of cookies might s till need a CSRF token as a header as of today unless it's a controlled environment.
Personal Opinion held loosely.
Do no harm. Cookies add "harm"/work that you have to mitigate.
Cookies might protect attacks leaking access tokens but why would an attacker care about the access token when they can run any code they wish?
LocalStorage weakness is XSS, but Cookies does not protect against that.
What prevents them from just taking the password?
Popping up a login modal to an unexpected user that won't think twice, hell Github does that from time to time for good reasons, it's not unheard of.
From what I understand AuthCookie, that is created by FormsAuthentication, takes care of encrypting (am I right?) and creating the Auth Token. Once created, the token/authCookie is passed on every client <-> server communiqué
From what I understand to keep the token from being highjacked, we need to put the site under SSL (HTTPS)
Quesetion #1: will AJAX calls compromise the security of our site? will they even work under HTTPS.
Question #2: We use IIS7.5 and some of our pages don't require a secure login; but given the AuthCookie, I guess it's best to put everything under HTTPS. will there be a noticeable performance drawback with this approach? what are some of the other disadvantages?
cheers
Your understanding is correct. ASP.NET manages the encryption of your FormsAuthentication token, which is the value of your auth cookie and this prevents tampering, but if sent over the wire via HTTP it is suceptible to third-party theft leading to session hijacking.
To your specific questions:
No, AJAX calls should not compromise the security of your site, specifically because they should indeed work over HTTPS.
Yes. You should run everything under HTTPS when you have a website that requires authentication. With relatively modern computers, the performance impact of running under HTTPS should be minimal. It's always valuable to test given your specific scenario, of course, but as a rule, the impact is a single digit percentage or less, and is not what one would generally consider to be noticeable.
I'm using Codeigniter sessions for logging in users. For reasons that have always been mysterious to me, sometimes a user session gets destroyed and they have to log in again.
Because Codeigniter sessions are cookie based I assume I need to be looking at the browser to try to understand why the cookie got destroyed.
First of all, is that true? And if so, might someone suggest a method (php, js, browser dev tools?) to log the errors that lead to each session getting destroyed?
I would try checking the cookie timeout setting in ./application/config/config.php and make sure this isn't something ridiculously low.
$config['sess_expiration'] = 7200;
There are many other potential causes for this behavior, all of which depend on your environment. For instance:
If your code runs on multiple servers behind a load balancer not
configured for "sticky sessions", then you will hit a new server
(potentially) for every request, causing your session to be
recreated.
If your website utilizes multiple domains, your cookie will not be
valid for all domains, only the one who created it.
But without knowing anything about your code or environment, I would recommend using firebug or chrome developer tools to check your cookie from your browser while checking what is being requested and responded in the network layer.
I am currently working on the authentication of an AJAX based site, and was wondering if anybody had any reccomendations on best practices for this sort of thing.
My original approach was a cookie based system. Essentially I set a cookie with an auth code, and every data access changed the cookie. As well, whenever there was a failed authentication, all sessions by that user were de-authenticated, to keep hijackers out. To hijack a session, somebody would have to leave themselves logged in, and a hacker would need to have the very last cookie update sent to spoof a session.
Unfortunatley, due to the nature of AJAX, when making multiple requests quickly, they might come back out of order, setting the cookie wrong, and breaking the session, so I need to reimplement.
My ideas were:
A decidedly less secure session based method
using SSL over the whole site (seems like overkill)
Using an iFrame which is ssl authenticated to do secure transactions (I just sorta assume this is possible, with a little bit of jquery hacking)
The issue is not the data being transferred, the only concern is that somebody might get control over an account that is not theirs.
A decidedly less secure session based method
Personally, I have not found using SSL for the entire site (or most of it) to be overkill. Maybe a while ago when speeds and feeds were slower. Now I wouldn't hesitate to put any part of a site under SSL.
If you've decided that using SSL for the entire site is acceptable, you might consider just using the old "Basic Authentication" where the server returns the 401 response which causes the browser to prompt for username/password. If your application can live with this type of login, is works great for AJAX and all other accesses to your site because the browser handles re-submitting requests with appropriate credentials (and it is safe if you use SSL, but only if you use SSL -- don't use Basic auth with plain http!).
SSL is a must, preventing transparent proxy connections that could be used by several users. Then I'd simply check the incoming ip address with the one that got authenticated.
Re-authenticate:
as soon as the ip address changes
on a time out bigger than n seconds without any request
individually on any important transaction
A common solution is to hash the user's session id and pass that in with every request to ensure the request is coming from a valid user (see this slideshow). This is reasonably secure from a CSRF perspective, but if someone was sniffing the data it could be intercepted. Depending on your needs, ssl is always going to be the most secure method.
What if you put a "generated" timestamp on each of the responses from the server and the AJAX application could always use the cookie with the latest timestamp.
Your best bet is using an SSL connection over a previously authenticated connection with something Apache and/or Tomcat. Form based authentication in either one, with a required SSL connection gives you a secure connection. The webapp can then provide security and identity for the session and the client side Ajax doesn't need to be concerned with security.
You might try reading the book Ajax Security,by Billy Hoffman and Bryan Sullivan. I found it changed my way of thinking about security. There are very specific suggestions for each phase of Ajax.