Tuesday, March 22, 2011

Website Security - How to avoid using session variables for logged in users

Hi,

It is a very common practice of storing logged in user details such as username, first name, last name, user id etc in session variables. But even session variables can be vulnerable and easily hacked. I have come up with a strategy of storing user details in runtime without using session variables or cookies. You will find a sample source code at the end of the post.

The idea is very simple. Assuming I have a user table with the following schema and data:


Now when the user is logging in through login.php, first the data is validated with the above table. If user has entered correct credentials, instead of storing the user data in session variables, I am storing them in a separate log table as follows:


with the code:


$is_user=mysql_fetch_array(mysql_query("select * from users where username='".mysql_real_escape_string($_POST['username'])."' and password='".mysql_real_escape_string($_POST['password'])."'"));
if(empty($is_user)){
$message="Incorrect username or password";
}
if(!mysql_fetch_array(mysql_query("select * from user_log where sessid='".session_id()."'"))){
mysql_query("insert into user_log set userid=".$is_user['id'].",sessid='".session_id()."',dt='".date("Y-m-d",time())."'");
}


In the above, after user logs in the session id and the user details along with the current date is stored in the log table as above. In this case I am just storing the userid, but you can add more fields, such as first name, last name etc.

(note: I am not using any encryption for storing password, but it is highly recommended)

This was just half the job. Next is to check whether user is logged in or not. During this checking we will run a query to check whether there are any records with the current session ID. If a match is found the user is valid. This is done by:



if(!mysql_fetch_array(mysql_query("select * from user_log where sessid='".session_id()."'"))){
header("location: login.php");
}

If record is not found, the user is redirected to the login page. Now you must be concerned about the performance, as you need to run a query every time the page loads. Well in that case, since the session ID and userid are always fixed so you can put the log table under memcaching (see memcache with cakephp and simple query caching). That solves your performance issue as well.

So, there you go. You are not using any session variables, yet keeping track of the logged in users details.

Click here to download the sample source code with the database schema. Finally you need to create a daily one time cronjob which would delete all the records in log table which are more than a day old by checking the "dt" field in the log table.

Apart from this, you can also take a file approach for storing the user log instead of log table, to further improve performance, but be sure to delete them at the end of the day, else your server might get jammed up.

Cheers!!


No comments:

Post a Comment