Cookie security
Introduction
When using cookies for login systems it’s very common to store the username and a hashed password. This method is nothing near ideal, since cookie theft is a very common phenomenon, whereby a potential hacker will be able to brute force your user’s password. What you want to do instead is creating a cookie containing 3 values: The username, a long random string and an expirery date. By putting the cookie information in a database as well, we can determine the cookies validity.
How to do it
NOTE: This guide presumes that you’ve already got a login system and the variables $username and $id is respectively the username and user id in your userdatabase
First you need to create a MySQL database table with the following data:
- id, int(11), unsigned, auto_increment, primary key
- user, varchar(50)
- random, varchar(64)
- expire, varchar(40)
- uid, int(11)
When you have authorized the user’s login data, you will generate the cookie information somewhat like this:
1 2 3 4 5 6 7 8 | $random = hash(sha256,(uniqid(rand(), true)) . (uniqid(rand(), true))); $expire = time() + 60*60*24*30; // current time + expirery time (here: 30 days) $name = "login"; // Name of the cookie $value = "$username\n$random\n$expire"; // Value of the cookie $query = "INSERT INTO `cookie_user_db` (`id`,`user`,`random`,`expire`,`uid`) VALUES (NULL, '$username', '$random', '$expire', '$id_db')"; mysql_query($query); $path = "/"; // The cookie will work in all folders on present domain. setcookie($name, $value, $expire, $path); |
In the code above it’s presumed that the $username string has already been properly evaluated, to prevent from mysql-injection attacks. See more here.
Now we have a cookie with our wanted data, and a copy of those data in our database.
When a user, who is not logged in, comes to your site, who has a cookie, we want to determine wether the given data is valid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | if($_COOKIE['login']){ $info = explode('\n',$_COOKIE['login']); // Devides the cookie in it's seperable values: 1) Username, 2) A unique random number and 3) the expirery date for the cookie. $username = mysql_escape_string($info[0]); // mysql_escape_string is used to prevent mysql injection attacks. $random = mysql_escape_string($info[1]); $expire = mysql_escape_string($info[2]); if($username && ($username == htmlentities($username)) && $random && $expire){ // Checks if a username is present and wether the username holds special characters. $query = "SELECT * FROM `cookie_user_db` WHERE `user` = '$username' AND `random` = '$random' AND `expire` = '$expire'"; $result = mysql_query($query); if(mysql_num_rows($result) >= 1){ while($r=mysql_fetch_array($result)){ $username_db= mb_strtolower($r["user"]); $random_db=$r["random"]; $expire_db = $r["expire"]; $uid_db = $r["uid"]; } //checks wether the supplied user exists in the user database $result = mysql_query("SELECT * FROM `$user_db` WHERE `user` = '$username' AND `id` = '$uid_db'"); if(mysql_num_rows($result) >= 1){ // At the basis the user isn't allowed to login: $login = false; if (($expire_db == $expire) && $expire > time()){ // Checks wether 1) the expirery date of the database matches the one supplied in the cookie and 2) wether the expirery date is still valid. // Gives $login a true value $login = true; } // Checks wether $login is true if ($login == true) { // Session variable "access" is given a true value. $_SESSION['access'] = true; // The user is sent to the administration page. header("Location: admin_website.php"); exit; } //If $login is not true, the user is sent back to the login page. else { include("login.php"); exit; } } } } } // If no cookie is found, the user is sent back to the login page include("login.php"); exit; |