How to protect my JSESSIONID from document.execCommand(“ClearAuthenticationCache”)? - session

This might be a duplicate of this question, but the solution proposed isn't viable for us:
Protect against 3rd party callers of document.execCommand("ClearAuthenticationCache")? Clears our session cookies
Long story short: IE has a way to clear session cookies using JavaScript - document.execCommand(“ClearAuthenticationCache”). This is used in a variety of web apps including Outlook Web App (and presumably many others). Problem is MS in their infinite wisdom decided that this command should clear session cookies for all open sites (can you tell I'm a little bitter, it took me months to find the source of randomly missing JSESSIONIDs).
We use JSESSIONID as well as another token to make sure the user is authenticated. The JSESSIONID is secure and httpOnly. This works well except when the JSESSIONID is wiped out by a third party. So my question is in two parts:
Is there a way I can protect my session cookies from this (let's assume anything involving client side configuration, such as pinning or registry hacks, is a non-option)?
If not, is there a way for me to securely recover from this? Since the JSESSIONID is httpOnly, the browser shouldn't be able to read it, but maybe there is something I'm not thinking off.
If relevant: we use Tomcat 7 as our webserver. The app is a fairly complex SaaS app, and security is fairly important.
Thanks all.

I believe either of the following options would work to protect servlet sessions from document.execCommand(“ClearAuthenticationCache”):
You could set the max-age of your JSESSIONID in your web.xml. That way your JSESSIONID cookie would no longer be a session cookie! This would make your web application slightly less secure as the cookie would still survive after the browser is closed.
You could abandon HTTP cookies altogether and configure Tomcat to do session tracking with the SSL session ID. I've never actually configured it myself, but I would guess that this is more secure than using JSESSIONID cookies. However, session replication is not possible in this configuration.

Related

Is there a way to check the authenticity of the user, after changing the Session Cookie?

Steps to re-create the issue:
Login with Admin Credentials and copy the session cookie.
Open another browser, Login as another user, paste the session cookie of the admin. Refresh the page. Now, you'll be
logged in as Admin.
How to solve this issue? Any suggestions would be of great help.
Tried using the event subscriber to get the previous session before drupal loads the cookie session, but no luck with it.
This is not a problem, I mean, of course, Session Hijacking is a really big concern - but standard defences are fine.
These are the controls that I know are widely known/used:
Ensure HTTPS is used everywhere,
Only use a securely created random string for the cookie value,
Set the secure flag on all cookies. This will ensure that they are only sent over an SSL connection,
Change the session cookie on each new login attempt.
All of Drupal 8's cookies are secure by default.
The exception is BigPipe's no-JS cookie, see https://www.drupal.org/node/2678628 — but there are no security consequences there.
I know some very sensitive applications may also store - for each session - the following additional information:
SSL Session ID
HTTP User Agent
Remote IP Address
In my point of view, I wouldn't bother with checking the HTTP User Agent or the remote IP address. They don't add that much security and they will break legitimate use in certain scenarios. Checking the SSL session ID (SSL session binding) would be OK from a security perspective, but could be painful to implement, the other defences are fine.
If your concern is Cookie Theft via XSS, the best defence is to use standard methods to avoid XSS bugs in your web application. See OWASP for plenty excellent resources.
You may find a lot of best practices to write secure code for Drupal 8 here: https://www.drupal.org/docs/8/security/writing-secure-code-for-drupal-8
You may also find a pretty old discussion about this on Drupal here: https://www.drupal.org/project/drupal/issues/19845

AJAX withCredentials not passing along cookies in Safari

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.

Token-based authentication for web app: how to cache token?

I'm trying to switch a web app from the "traditional" cookie-based authentication mechanism to a purely token-based one. The token should be cached once received by the client to reduce overhead. What is the best way to store the token?
This is what I already learned from googling:
The first promising avenue I looked into was browser session storage, however, as far as I can tell, this isn't shared even across tabs, which means if users follow a link from the site using a new tab, they will have to log in again.
There's also local storage, but I want users to automatically be logged out when they close their browser, and I'm also a little uneasy about tokens sitting around in the storage, even though I expire them server-side. It just seems unclean.
Another way is to store the token in a session cookie, which would mean it both gets killed on browser close and can be shared across tabs. It's almost ideal, except the cookie will of course get sent over the wire with every trip to the server, which I would like to avoid if possible. Even though it's not a security issue, it seems redundant to be sending it via the cookie as well as in the HTTP Authorization header. I've thought about setting the cookie path to a non-existent path on my domain, but that's not exactly an epitome of beauty either...
So, being faced with three non-optimal solutions, I once again turn to SO for help. How do you guys do it? What's the best way?
tl;dr What is the canonical way of persisting authentication tokens in single-page web applications?
t;dr I'm using localStorage to store token.
I'm using localStorage for storing token on client side. You can see details of my implementation in my article: React Token Based Authentication to Django REST API Backend.
The localStorage shares the token across tabs and doesn't disappear when you close the tab. The data in localStorage persist until explicitly deleted. The data in sessionStorage is deleted when the session ends.
There is some discussion on the internet that localStorage is insecure because, in the case of the XSS attack, a hacker can read all data from it. Which is true. There is some discussion that httpOnly cookies are better to store the token because hackers cant access and read the token from the httpOnly cookie. It is true, but the misunderstanding is that cookies don't prevent XSS (the XSS can occur even if you use httpOnly cookies). What is more, cookies enable CSRF attack. And, in the case of XSS, a hacker can still use set httpOnly cookies for malicious requests (similar to CSRF). So there is no clear winner here. The most secure way is to not store tokens on the client side.

What does `<script>` do, in a url?

In this document, page 7, it describes a vulnerability that may happen when a user is tricked into going to
"http://online.worldbank.dom/<script>document.cookie="sessionid=1234;domain=.worldbank.dom”;</script>.idc". (They also include a url with <meta> at the end, as an example.) I noticed that at least in Firefox, this only gives 404 error. For example, http://example.iana.org/%3Cscript%3Ealert%28%27hi%27%29;%3C/script%3E.htm
I know there's javascript: "url" prefix, but was there also a bug in old browsers that somehow allowed scripts in the url? Or is this document implying something completely different?
One other thing I don't quite understand - on page 11:
"Notes: It’s important to realize that using an encrypted
communication between the user’s browser and the target web server has
literally no effect on the exploitability of session fixation
vulnerabilities."
It says this in the section that describes network sniffing and injecting, is that really possible with https??
The idea with session fixation is that the attacker doesn't need to pay attention to whether or not it's https. Sniffing is not needed.
Normally the attacker could try to steal a valid session id by sniffing, and then take over the user's session. With session fixation the attacker picks a session id, and then tricks the victims browser into using that preselected session id. Thus there is no need to sniff. The session id is already known.
Regarding script-tags in the url, that attack will work in some, but not all websites. If the website has (as described) a cross site scripting (XSS) then the attacker can craft a url with a fixation attack. However a more likely scenario is injecting scripts that steal the current session id, but this may not work if the session cookie is httpOnly. In this case session fixation might be a better option for the attacker.

Best way to secure an AJAX app

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.

Resources