6

On Google Chrome (I saw this with version 35 on Windows 8.1, so far I didn't try other versions) when browser crashes (or you simply unplug power cable...) you'll be asked to recover previous session when you'll open it again. Good feature but it will restore session cookies too.

I don't want to discuss here if it's a bug or not anyway IMO it's a moderate security bug because a user with physical access to that machine may "provoke" a crash to stole unclosed sessions with all their content (you won't be asked to login again).

Finally my question is: how a web-site can avoid this? If I'm using plain ASP.NET authentication with session cookies I do not want they survive to a browser crash (even if computer is restarted!).

There is not something similar to a process ID in the User Agent string and JavaScript variables are all restored (so I can't store a random seed, generated - for example - server side). Is there anything else viable? Session timeout will handle this but usually it's pretty long and there will be an unsafe window I would eliminate.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
  • Using the `beforeunload` event to explicitly delete cookies is effective. You may want to use localStorage to keep track of how many tabs are open for your site. – ZachB Jul 31 '19 at 09:43
  • @ZachB tnx, I tried to reproduce this one year ago (or so) and it seems to be _resolved_ but, anyway, I can't use `beforeunload` because it's not called when the browser crashes (or you simply remove the power cord from the computer...) and they were the two cases I was writing about. – Adriano Repetti Jul 31 '19 at 10:52

2 Answers2

2

I didn't find anything I can use as process id to be sure Chrome has not been restarted but there is a dirty workaround: if I setup a timer (let's say with an interval of five seconds) I can check how much time elapsed from last tick. If elapsed time is too long then session has been recovered and logout performed. Roughly something like this (for each page):

var lastTickTime = new Date();

setInterval(function () {
    var currentTickTime = new Date();

    // Difference is arbitrary and shouldn't be too small, here I suppose
    // a 5 seconds timer with a maximum delay of 10 seconds.
    if ((currentTickTime - lastTickTime) / 1000 > 10) {
        // Perform logout
    }

    lastTickTime = currentTickTime;
}, 5000);

Of course it's not a perfect solution (because a malicious attacker may handle this and/or disable JavaScript) but so far it's better than nothing.

New answers with a better solution are more than welcome.

Adriano Repetti
  • 65,416
  • 20
  • 137
  • 208
1

Adriano's suggestion makes is a good idea but the implementation is flawed. We need to remember the time from before the crash so we can compare it to the time after the crash. The easiest way to do that is to use sessionStorage.

const CRASH_DETECT_THRESHOLD_IN_MILLISECONDS = 10000;

const marker = parseInt(sessionStorage.getItem('crashDetectMarker') || new Date().valueOf());

const diff = new Date().valueOf() - marker;
console.log('diff', diff)

if (diff > CRASH_DETECT_THRESHOLD_IN_MILLISECONDS) {
    alert('log out');
} else {
    alert ('ok');
}

setInterval(() => {
    sessionStorage.setItem('crashDetectMarker', new Date().valueOf());
}, 1000)

To test, you can simulate a Chrome crash by entering chrome://crash in the location bar.

Don't forget to clear out the crashDetectMarker when the user logs out.

Patrick McElhaney
  • 57,901
  • 40
  • 134
  • 167
  • 1
    One note about the date (I had the same problem with the code I posted): it's local time then it will incorrectly calculate the interval when transitioning to/from the summer time, just need to use UTC here. It used to work just because Chrome restored the (I suppose...) whole JS state (or its last snapshot). I never investigated and now it seems that Chrome works as expected... – Adriano Repetti Nov 26 '19 at 14:26