Welcome back! If you missed Part 1, check it out here.
HTTP is a stateless protocol, hence the web server does not maintain any records of user activity. To track user activity, we generally use Sessions. There are various ways of session management where the server generates a session identifier (ID) initially and ensures that the same ID will be sent back by the browser along with each subsequent request. This helps us to maintain a record of users. Improper handling of these session variables could be a serious threat and allow attackers to gain access to the system. This article illustrates session fixation, using ASP.NET web applications as our example. For a better understanding, I have created a simple ASP.NET application. You can download the project from here. This project has two folders ‘SecureLoginFunc’ and ‘InsecureLogin’ which contains the login and logout mechanism of the application. You need to import the downloaded project to Visual Studio or create a virtual directory in IIS and add this project to it.
As you know, a Session is used to track the user activity using a Cookie. In ASP.NET, the server creates a cookie named as ‘ASP.NET_SessionId’ on the client. This ‘ASP.NET_SessionId’ cookie value will be checked for every request to ensure the authenticity and Identity. ASP.NET has two ways of transmitting session IDs back and forth to the browser, either embedded in the URL or through a session cookie. You can easily spot the session ID when it’s embedded in the URL, for example ‘www.abc.com/(S(dacaanfdgasdfdadfghq)).’ Anyway, this is not a recommended solution.
Session Fixation is a specific attack against the session that allows an attacker to gain access to a victim’s session. An attacker visits the website to obtain a valid Session. This valid session cookie is placed in the victim’s browser. When the victim logs into the website, both the attacker and the victim will use the same session cookie that the attacker already knows, and thus the attacker-owned cookie is now authenticated and can be exploited.
Let’s look at this vulnerability in practical terms using an ASP.NET application. Once you import the project into Visual Studio, open the file ‘Login.aspx.cs’ in ‘InsecureLogin’ folder. This is a code behind file for our login functionality. As you can see, there are two events: ‘Page_Load’ and ‘btnSubmit_Click.’ Upon clicking the Login Button, the event ‘btnSubmit_Click’ will be triggered. Let’s understand the code before running the application. When a user provides valid credentials, a Session called ‘userLoggedin’ would be created and get stored on the server side. Once the login is processed, the user will be redirected to the ‘Welcome’ page which has a log out button.
Now open the file ‘Welcome.aspx.cs’ in the ‘InsecureLogin’ folder. This is a code behind file for the welcome page. Once the user is redirected to this page, an event called ‘Page_Load’ should be triggered first. And this event would check that the value of Session is not null and enable the logout button. When the user clicks on the logout button, the ‘btnLogout_Click’ event will be triggered which clears the Session and redirects the user to the login page
Now run the web form Login.aspx (Press F5) from Visual Studio. Press F12 to view the cookies before logging into the application.
Once you log in with valid credentials, a cookie ‘ASP.NET_SessionId’ will be created. To Illustrate this, I have captured the value of the cookie and displayed it on the welcome page.
As per our understanding from the code review, when a user clicks on the logout button, the session has to be terminated. But if you notice, the cookie ‘ASP.NET_SessionId’ still exists and is still valid. This valid cookie value can be used by the attacker to hijack the user session using a few techniques such as phishing, or cross site-scripting which exploits this pre-defined cookie on a victim's browser. When the user clicks this link and logs in, the user will have the same ASP.NET_SessionId cookie value that the attacker knows and thus the attacker can gain access to the user's account. This attack is known as Session Fixation.
As you have seen that the cookie ‘ASP.NET_SessionId’ wasn’t deleted upon user logout. So we need to delete this cookie explicitly on the logout event. But it really won’t solve the problem. Since we are entirely relying on one cookie, ‘ASP.NET_SessionId,’ anyone who has this cookie can gain access to the account. This can be achieved by sniffing/MitM (Man in the Middle Attacks). So to overcome this problem we will create another cookie, ‘AuthToken,’ that has random a GUID as its value.
Also, we will create another session, ‘AuthToken,’ with the same random GUID as its value. Let’s take a practical look at this with an example. Go to the folder ‘SecureLoginFunc’ and open ‘SecureLogin.aspx.cs.’ As you can see, upon clicking the login button, the event ‘btnSubmit_Click’ will be triggered. This event creates two Sessions, one for user authenticity and another session for integrity.
Once the user has logged in with valid credentials, two sessions and cookies will be created and the user will be redirected to the ‘SecureLogout’ page. Open the ‘SecureLogout.aspx.cs’ code behind the file. When the page loads, we will check three conditions. Both the sessions and cookies should not be null. And the value of the Session ‘AuthToken’ must be equal to the value of the cookie ‘AuthToken.’ Since the ‘AuthToken’ value is a random GUID, it's practically impossible to predict the AuthToken value. If any of these conditions fail, the user will be redirected to the login page
When the user clicks on the logout button, the ‘btnLogout_Click’ event will be triggered. This event removes all sessions. Also, we are explicitly removing the values of thecookies ‘ASP.NET_SessionId,’ and ‘AuthToken’ so that an attacker cannot fixate the session.
Apart from the above implementation, use HTTPOnly, secure flags for cookies. Also never use Cookieless sessions, since sessions can easily be manipulated in query strings. Implement Session Timeout for short spans of time.