Session Puzzling Attack: an artistic way of bypassing authentication

Singh M.
5 min readJul 6, 2020

--

First things first, a BIG THUMBS UP to the person who discovered this attack. Its just genius. Unfortunately I don’t know the name, if you do then please comment. Well, I came to know about this attack from my senior Mr. Rishabh Pandey who himself is an excellent Pentester and have been a great mentor to me. Since then, I have discovered it in some applications that I’ve audited during my career.

This article will cover the basic understanding behind the attack and a quick step by step demo on how to test it.

Well this will be easy for you if you have the basic idea of how HTTP session works. If you don’t, you may read my article: Cookie+Session: Story of a Stateless HTTP and join back.

Okay, here it goes….

What happens when you visit a website?

A new HTTP session is created. The “id” of the session is given to your HTTP Client (Browser) to keep it and send it in future requests so the Server could identify you based on that session id.

What happens when you login into the website?

When you login into a website or an application it verifies who you are and if you are who you are claiming to be. In tech terms we call it “identification” and “authentication”. The application will validate the credentials you have provided and act accordingly.

Your credentials are found valid and you are authenticated. But what actually happened?

See session is basically an Object (OOPS!) and objects have attributes. Similarly we can add attributes in the session object and use their values whenever needed. These are called “session variables”. Therefore, when you get authenticated, a session variable is created say “username” and its value is set to your username, the one that you used to login. This process is commonly called “mapping the session to/with the user”. Now this session variable will be used to filter out the resources in the website that are specifically private to you.

Creating a session variable is fairly simple. Below are a couple of examples:

In PHP

$_SESSION[‘firstName’] = “Mahesh”;

In ASP.NET

Session(“firstName”) = “Mahesh”

Whats wrong with this?

This process of having a session variable that contains the user id, username or whatever the developer felt necessary to use is great for displaying personalized results. It becomes a problem when this session variable is also used to verify if the user is authenticated.

Most developers keep in mind a simple workflow for user authentication.

User opens the login form and enters his/her credentials.

User sends a request for login.

If the credentials are valid: User gets redirected to home page.

Else: User gets redirected back to the login page.

Similarly there is a workflow for reset password functionality.

User opens the forgot password page and enters his/her username.

User sends a request for reset password.

If the username is valid: An email containing the reset password link gets sent to the user’s registered mail id.

User clicks on the link and enters the new password.

Else if the username is invalid: User gets notified with an error.

But hackers usually don’t like to do as they are told. They prefer exploring and doing something that’s unexpected. Here is an example:

Hacker opens the forgot password page and enters a username that he/she knows or presumes to be valid .

Hacker sends a request for reset password.

If the username is invalid: Hacker gets notified with an error and hacker attempts a new username.

Else if the username is valid: An email containing the reset password link gets sent to the mail id registered with the username.

Hacker sends a request to access the home page.

Usually when a reset password request is sent to the server, a session variable is created that stores the username. This session variable can be later used in conditions of the UPDATE query for change password and also for validating the token in the reset password link.

Also, when a login request is sent and the user is authenticated, a session variable is created that stored the username. So when the user opens the home page or edit profile page, this session variable is used inside the conditions of SELECT queries to display the data specific to that user.

And it is very common to use the same name for the session variable in both the cases as they contain the same data.

Therefore, if there is no additional logic to check if the user is authenticated, the “hacker” in the above mentioned scenario will definitely get access to the home page of the user whose username was used in the reset password request.

Here is an example:

In my demo application I opened the forgot password page, entered a valid username and clicked on send:

Open the Forgot Password page and enter a valid username.
Success message appears indicating that the mail is sent.

This is the forgot password code that got executed on the application server:

A part of the code that got executed.

As you can see in the above picture, a session variable is created by the name ‘userid’ and its value is the username in the post request.

Next, I entered the URL of the edit profile page in the URL box and hit enter:

Without even authenticating into the application, I was able to access the edit profile page.

This happened because, the application creates a session variable “userid” when a user logs in and set its value to the username. This session variable is then used in SELECT queries to display results specific to the user. There is no additional check to validate if the user is authenticated or not.

How can this be resolved?

Its quite simple, just create a session variable like “authenticated” and set is value to true when the login attempt is successful. And check the value of this session variable at the start of each post authentication page to check if it’s true.

For e.g. in PHP it could be written as:

if($_SESSION[‘authenticated’]!=true){

header(‘location: login.php’);

exit();

}

Conclusion

I hope the article was comprehensive. Your thoughts are welcomed in the comment section.

--

--