Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Session timeout does not tolerate system time changes #2175

Open
danielfrankcom opened this issue Aug 30, 2022 · 1 comment
Open

Session timeout does not tolerate system time changes #2175

danielfrankcom opened this issue Aug 30, 2022 · 1 comment

Comments

@danielfrankcom
Copy link

danielfrankcom commented Aug 30, 2022

The Session object has built-in handling for timeouts, but it uses System.currentTimeMillis() as its source of time. This is affected by operating system time changes, which has a number of strange/problematic effects:

  1. A time change forward shortens or immediately invalidates the session
  2. A time change backward lengthens the session or makes it effectively perpetual

In our application we are using the session timeout to invalidate the user's authentication, so this behavior has some pretty undesirable effects and possible security implications.

Devices that are connected to an NTP server may be affected by this behavior shortly after startup, when the time resynchronizes with the server. On some devices it may also be possible for an unprivileged user to modify the system time as a way to circumvent authentication time limits on the server.

Would it be possible to use System.nanoTime() as a monotonic time source for the session expiration calculation?

Scenarios

The scenarios below assume the following request handling code:

public void service(Request request, Response response) throws Exception {
    final Session session = request.getSession();

    if (session.isNew()) {
        System.out.println("New session used");
        session.setSessionTimeout(TIMEOUT_MILLIS);
    } else {
        System.out.println("Old session used");
    }
}

Time moves backward

Scenario

final long TIMEOUT_MILLIS = 10_000; // 10 seconds.
  1. Run server using the code above
  2. Send first request
  3. Change system time by -2 minutes
  4. Wait 15 seconds
  5. Send second request

Expected

Output should be:

New session used
New session used

No request is made to the server within the 10 second timeout. The session should expire, and the next request should trigger the creation of a new session.

Actual

Output is:

New session used
Old session used

The expiry calculation uses the underlying system time (which was moved backwards), so the session is not yet expired even though more than 10 seconds have passed.

Time moves forward

Scenario

final long TIMEOUT_MILLIS = 60_000; // 1 minute.
  1. Run server using the code above
  2. Send first request
  3. Change system time by +2 minutes
  4. Send second request

Expected

Output should be:

New session used
Old session used

A request is made to the server within the 1 minute timeout. The session should still be valid, and should be reused.

Actual

Output is:

New session used
New session used

The expiry calculation uses the underlying system time (which was moved forwards), so the session is immediately expired. A new session is created as a result.

@mnriem
Copy link
Contributor

mnriem commented Sep 8, 2023

@danielfrankcom Can you create a reproducer and a PR with suggested enhancements?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants