7

Background:

Most browsers have implemented some form of "Session Restore" functionality as a convenience to users where, if enabled, session cookies will be persisted across browser restarts.

The browser vendors have a defensible position for keeping these features. This puts the onus on users to configure their browsers "correctly" and/or manually log out of the sites before quitting the browser.

Question:

For a site that provides access to highly sensitive data AND is used in shared computing environments, what are the best practices for guaranteeing that a session is destroyed when the browser is closed?

Possible ideas include:

  1. Listening for onbeforeunload events or similar and counting the number of open windows or tabs. When the count goes to 0, send a message to the server to invalidate the session. This seems problematic, due to: a) cross browser event-handling quirks, and b) navigation away from the site, intentional or accidental, would be treated the same as closing the last tab or window.
  2. Implementing a "heartbeat" in the client code that once absent for a period of time invalidates the server session. This also seems challenging due to: a) network latency possibly causing false-positive logouts, and b) some browsers suspending JavaScript code for backgrounded tabs (or applications on mobile).

Are there any other approaches that are reliable across the various web platforms? What are the highest-security websites currently doing in this space?

  • If there's really sensitive data involved, keeping user separation is more a task for the maintainers of the workstations than for you. They should configure the browsers in order to discard cookies when the browser closes, and tell the users to actually close the window when the work is done. If the admins don't care for security issues, you have lost either way. – user10008 Dec 25 '14 at 3:55
  • Unless the workstations are in a controlled environment, you cannot depend on workstation security or browser configuration, and even if they're in a controlled environment, it's a dicey situation. – Bob Brown Dec 26 '14 at 18:04
2

The best here would be to use a combination of cookies AND Rolling session IDs in URL (where a session id is put after the Query, like thisfile.php?sess=biskgndjkgnsldgsgdj) where this session ID Changes with each request.

This ensures only one tab or browser window is valid at one specific time.

Then you use the heartbeat system. The heartbeat can easly be constructed to send like 1 beat per 4th second, giving 15 beats per minute. And then logout the user on server-side if ALL beats are absent for a whole minute.

15 beats are not going to get "delayed or lost" due to network latency. If one single beat arrives to the destination, timer is reset and allows up to 15 beats missing again.


Note: You CANNOT prevent that sensitive information is visible in the last browser window visible, since that is often based on information cached in the client, even if you use no-cache and no-store pragmas. Thats why you should construct the UI to require a separate action for each opening of sensitive information dataset. Requiring a separate action also make sure you can log the access to each dataset.

Example for a Medical data application (change to fit your application): Lets say that you in Medical application can view a patients adress, a patients medicine history and patients 10 last visits.

Instead of showing all data on same page, allowing this information to be unauthorizedly cached, you can for example instead have a button to "reveal patients adress", a button to "reveal medicine history" and a button to "reveal patients 10 last visits", all these do a request to the server.

Thus if the user of application never press "reveal patients adress", then Anonymous medical data is going to be cached on the client.


If application has some sort of transaction log containing highly sensitive data, its better to split it up in Days, weeks, months or whatever is suitable with regards to how frequent events is, so each block of log data must be opened separately.

  • Unless those "reveals" are done with Ajax, they'll be cached. – Bob Brown Dec 26 '14 at 18:03
  • I agree network latency is unlikely, but you haven't addressed the other potential problem Jack mentioned of the browser suspending javascript. That's an issue, but I'd say the website is going to be rather broken if javascript doesn't work for a whole minute. Requiring user interaction at every data reveal is a huge usability problem. Security always needs to be balanced with user needs. – Steve Sether Dec 26 '14 at 20:51
  • @BobBrown : Yes, but the Point of the reveals is that you separate so you only reveal what you need to see, thus you only "expose" the information that you want to see. So lets take Another example: I can select to reveal my shipping adress and my credit card number. I select to only reveal my shipping adress - thus my credit card number never get revealed to client and never get cached. This in opposion to showing all information on the same page, so even potentially sensitive information you dont need to see, gets sent to the client and cached. – sebastian nielsen Dec 27 '14 at 0:09
  • About the tab issue: The main idea of having a changing session ID is to specifically prevent multi-window/multi-tabbed browsing on the sensitive site. That also gives security against session hijacking, since if the session is hijacked, the victim will be logged out and be able to detect the attack. And also, if the victim attempts to use a logged out session, a forced logout can be done on the whole session causing the attacker to be logged out aswell. Thus it can be seen as a advantage that a session is logged out if its left in a inactive tab for too long. – sebastian nielsen Dec 27 '14 at 0:12
1

You will need to track session state server side for this, and expire sessions that have not had any activity within the last X number of seconds. Say X is 60, which means that you will force logout on any sessions that haven't had any activity within the last minute.

If you do not want users to be logged out if they do not navigate to another page within each minute, you could have an AJAX keep-alive that will make a request to the page. I would suggest using X/2 seconds for this check to allow time network latency. So every 30 seconds your AJAX will fire, sending the session cookie to the server that will update the last action time recorded against the session to the server's current time.

You can still implement an inactivity timer that would expire the session if say you receive 15 minutes worth of AJAX keep-alives but no manual requests from the user.

At the end of the day, you need to realise that this is a client controlled situation so you can only take this so far. For example a user could auto refresh the page using a browser plugin to prevent automatic logout.

some browsers suspending JavaScript code for backgrounded tabs (or applications on mobile).

If this is a concern, you could increase the value of X. If you application is highly sensitive, then maybe user education is the key. Teach your users that they must log out when they have finished using your application. You could detect whether users are timing out or explicitly logging out, and if it is more often the former you could display a prominent message on your site.

What are the highest-security websites currently doing in this space?

There is a highly secure way, however this would need to be implemented from the ground up within your web application architecture and cannot simply be dropped in. This is where Session IDs are placed in hidden form fields instead of being contained within a cookie. However, they must be submitted by POST (i.e. in the request body). Using this in combination with disabled caching will prevent a session being continued between browser restarts.

The downside of this approach is that every navigation action is required to submit a form.

For example we could have a form to handle navigation on each page constructed like so:

<form method="post" action="/navigate">

    <input type="hidden" name="navigationPage" />
    <input type="hidden" name="sessionId" value="12345678" />

</form>

Upon a click within the navigation JavaScript will execute and set navigationPage to the appropriate value (e.g. myAccount, orderHistory, etc) and then submit the form. The /navigate URI will verify the sessionId and then navigate to the page specified in navigationPage if the session is valid. Using this method every page within your logged in session will have the same URI (www.example.com/navigate in this case).

This is more secure than adding a query string value in that the Session ID will not be leaked in referer headers in the case of any external links. External links can simply link directly to the resource and will not be the form POST that internal navigation uses.

Many banking systems employ a similar technique for extra protection against session hijacking within the session. In these scenarios sessionId in the hidden form field will be regenerated on each page load which ensures that only a single web browser is navigating at one time. However, this will prevent the use of the back button because it forces a resubmission of POST data, or of opening links in separate browser tabs because the rolling ID will not be updated in both places. This is often used in combination with session cookies but it can be used in isolation. Actions that require additional information like money transfers can simply include extra form fields to be submitted with the main form.

Another advantage of this approach is that it is inherently secure against CSRF. If another page makes a cross site request it will be missing the sessionId because it will not be automatically submitted the same way that cookies are.

This can also be implemented in HTML only without JavaScript, where each button on the page will submit an ID of the navigationPage.

This approach means you can also keep your current session timeout and there is no need for a heart-beat.

0

With the exception of supporting older versions of Internet Explorer, what I would do is use web storage to store large application states on the client side and allow the JavaScript to load the data up.

Web storage gives a lot more space around 5MB than cookies but I would also use cookies to store the authentication token.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.