Session persistence after logout
Gone but not forgotten: a developer's guide to a secure logout
JavaScript
What is session persistence after logout?
Session persistence after logout, also known as “logout does not invalidate the session,” is an often overlooked and downplayed security vulnerability found primarily on web applications. This vulnerability occurs when a user’s session isn’t properly terminated after they've logged out, leaving a valid session token behind that an attacker can leverage to take control of the account. This can pose a significant threat if the victim’s session is stolen or if the victim uses a public computer such as one in the library.
About this lesson
In this lesson, you will learn how session persistence after logout works and how to protect your applications against it. We will begin by exploiting a session persistence after logout vulnerability in a simple application. Then we will analyze the vulnerable code and explore some options for remediation and prevention.
Lisa is an enthusiastic software developer. She attended DevSecCon but in between sessions, she took a little break to digest everything the speaker was saying. She decided to share her thoughts about the event on her favorite tech blog using a public computer provided at the venue.
She logged in to her blog, shared a quick comment about the ongoing sessions, and logged out, thinking she had secured her account by doing so. She then went to attend another session, leaving the computer for the next user.
But here is where things took a dramatic turn. A few hours later, Lisa received an alert on her phone about unexpected activity on her social media account. Confused, she quickly checked her account and was taken aback by some posts she didn't make and messages she didn't send. What could have possibly gone wrong?
Here's what happened: the public computer Lisa used was the hunting ground for an opportunistic hacker. Despite Lisa logging out of her account on the blog, the session wasn't properly invalidated, and her session token remained active on the site.
In the scenario above, the problem originated in how the backend server handled user sessions. Let's look closer at a simplified example of how the backend code for this session handling might have been written.
Typically, when you log into an application, the server creates a unique identifier, called a session ID. This ID is stored on the server side, and a corresponding session cookie with this ID is sent to the client-side, which is your browser. This session cookie is what allows you to stay logged in as you navigate different pages on the website.
Here's an example of how the login functionality might look:
When you log out of the application, the server should invalidate or delete the session associated with your session ID, and the client-side cookie should also be deleted. However, in the case of the blog above, the logout functionality failed to invalidate the session properly.
Here is the code behind the logout function:
In this logout function, the server correctly clears the session cookie from the client's browser, giving the illusion of a successful logout. However, notice that it doesn't handle invalidating the session on the server side. This means that if someone else has access to an old session cookie, they could still use it to authenticate as the user who thought they had logged out.
Impacts of session persistence after logout
As seen in Lisa's experience at DevSecCon, the implications of incorrect session handling are far-reaching. A simple oversight, leaving a session token active post-logout, allowed a hacker to exploit the security flaw.
The immediate consequence is unauthorized access. An active session token grants a hacker the ability to impersonate the user, sending messages and manipulating account settings as if they were the original user.
This unauthorized access leads to an intrusion on privacy. With the ability to navigate a user's account freely, the hacker can view personal data, posts, comments, or any sensitive information associated with the account.
To remind us how critical it is to handle session persistence correctly, consider an escalated scenario where an active session token belongs to an administrator account. The hacker gaining access to such an account could perform actions with significantly more impact. This could range from altering user privileges and deleting user data to potentially causing service-wide disruption.
Mitigation primarily involves ensuring sessions are invalidated server-side during the logout process. This means that not only does the session cookie get deleted from the client's browser, but the session on the server side also becomes invalid.
By invalidating the session server-side, the server no longer recognizes the session ID, thus making it useless even if a hacker manages to obtain it. It’s akin to changing the locks to your house; even if someone has a copy of the key (the session ID), they can't get in because the locks (session on the server side) have been changed.
For added security, it’s also a good idea to implement session timeouts and invalidate sessions on significant account changes (like password changes). These measures can limit the time frame a hacker has to exploit an active session and further reduce the risk of session hijacking.
Now, let's revisit the logout function from the section above and see how we can modify it to correctly handle session invalidation.
Here's an example of a secure logout function:
In this new logout function, we added a line of code that invalidates the session associated with the provided session ID on the server. The invalidateSession
function works by removing the session from the activeSessions map, essentially marking it as invalid.
With this mitigation in place, the session ID becomes worthless after the user logs out, just as it should be. The user can confidently log out, knowing their session can't be misused after they've left the application.
Test your knowledge!
To learn more about session persistence after logout, check out some other great content:
- The matching CWE for this type of bug
- An OWASP guide for testing log-out bugs, including testing for proper state invalidation
- A post about ASP.NET sessions not being terminated after logout
- A CVE for this type of bug found in the wild