IT.COM

[TUTORIAL] PHP - Security with Cookies

Spaceship
Watch
Another quick tutorial I decided to write not so long after my last one. A question (or comment really) I always here is, "Why do you use cookies? They're so insecure."

Even though cookies are clear text and can be easily altered, this is not necessarily true. If your code checks in a somewhat redundant fashion, you should have no security issues at all!

Well, let's start with a functions.php file to create the login/logout functions and we'll work our way from there :)

This is more of an intermediate tutorial so I'll be assuming you know the basics of PHP at the bare minimum. So, what we'll do here (examine the code to figure out exactly) will be calling the cookie and during our "check" function will be checking the cookie redundantly against the database, etc.

functions.php
PHP:
<?php
/**
 * Secure Cookies Tutorial by RageD
 * (C) 2008 RageD
 *
 */
if(!defined("IN_SCRIPT"))
{
	print "Unauthorized Access";
	exit;
}

class Cookie
{
    /**
     * Error variable...
     *
     */
    var $err = '0';

    /**
     * Constructor :)
     *
     */
    function __construct()
    {
        // I normally code a MySQL connector function in my scripts which would
        // work like $this->GLOBALVAR->connect();
        // But since this is a snippet, we'll just be using the basics
        mysql_connect('localhost','USER','PASS');
        mysql_select_db('DATABASE');
        
        // See if we have any errors connecting...
        if(mysql_error())
        {
            $err++;
        }

        // Report errors
        if($err > 0)
        {
            print "We've encountered a MySQL Error!<br /><br />".mysql_error();
            exit;
        }
    }    

    /**
     * Login function, stores cookies, etc.
     *
     * @param $name
     * @param $pass
     * @bool $enc (true/false)
     */
    function login($name,$pass,$enc='true')
    {
        // Convert pass to md5 if encryption enabled. By default, it is.
        if($enc == true)
        {
            $pass = md5($pass);
        }

        // Now, let's continue! Query #1: Finding information :)
        $query = "SELECT * FROM users WHERE name='".$name."' AND pass='".$pass."' LIMIT 1;";
        $result = mysql_query($query);

        // Make sure the information given is valid
        if(mysql_num_rows($result) == 0)
        {
            print "Uh-oh! Incorrect login information.";
            exit;
        }

        // Passed the test, now set it...
        setcookie("PRACTICE[name]",$name, time()+3600); // Define the cookie. Let it expire after an hour
        setcookie("PRACTICE[pass]",$pass, time()+3600); // This is why encryption is recommended stores pass
	return;
    }

    /**
     * Logout function
     *
     * Deletes cookies :)
     *
     */
    function logout()
    {
        setcookie("PRACTICE[name]","", time()-10); // Send the cookies back, they forgot the milk! :(
        setcookie("PRACTICE[pass]","", time()-10); // No, seriously. The time()-10 means they expired 10 seconds ago
    }

    /**
     * Check function
     *
     * Finally, the security comes into play :)
     *
     */
    function check()
    {
	// Make sure a cookie is set too xD
	if($_COOKIE['PRACTICE']['name'] AND $_COOKIE['PRACTICE']['pass'])
	{
        	// Redundancy is beautiful *tear*
        	$query = "SELECT * FROM users WHERE name='".$_COOKIE['PRACTICE']['name']."' AND pass='".$_COOKIE['PRACTICE']['pass']."' LIMIT 1;";
        	$result = mysql_query($query);
        
        	// Check.. Grr.. They tried to pull a fast one :-| or something bugged?! :(
        	if(mysql_num_rows($result) == 0)
        	{
        	    print "Session Expired.";
		    $this->logout();
         	    exit;
        	} else {
            		if($_COOKIE['PRACTICE']['name'] AND $_COOKIE['PRACTICE']['pass'])
            		{
             	  	 print "It worked!"; // Probably can comment this out :)
            		}
		}
        }
    }
}
?>

Here's the index.php file to make this all come together a little bit.

index.php
PHP:
<?php
/**
 * Secure Cookies Tutorial by RageD
 * (C) 2008 RageD
 *
 */
// Script security :)
define("IN_SCRIPT", true);
require_once("functions.php");

// Define $session var for use of the "Cookie" class
$session = new Cookie;
$session->login("USER","PASS","false"); // Login :)
$session->check(); // Check
print "<br /><br />Let's print our cookie information:<br />Username: 
      ".$_COOKIE['PRACTICE']['name']."<br />
	Password: ".$_COOKIE['PRACTICE']['pass']."";

/**
 * I understand there are better ways to implement this into a script
 * However, my intent was to show the basics so people understand how
 * it all works. Other uses of the "Cookie" class (defined as $session) 
 * are below:
 *
 * $session->check(); // Will check cookies against DB
 * $session->login(USERNAME,PASSWORD,"true/false") // Enc should be 
 * either true or false. "True" recommended
 * $session->logout(); // Will obviously log a user out.
 *
 */

?>


To test this script, use this simple database.sql file for the database structure used here:
Code:
CREATE TABLE users (
  `id` BIGINT(10) NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(32) NOT NULL,
  `pass` VARCHAR(32) NOT NULL,
  PRIMARY KEY (`id`)
);

Well if there are any questions or anything, just let me know. This is just a basic overviewing kind of assuming a lot from you guys :P so contact me with anymore questions!

-RageD
 

Attachments

  • Cookie_Security_Tutorial.zip
    2.9 KB · Views: 50
2
•••
The views expressed on this page by users and staff are their own, not those of NamePros.
0
•••
I will check it out the very first thing in morning :) will have to install it on my localhost :) Thanks for the nice tutorial and code :xf.love:
 
0
•••
Thanks for rep guys, hope this helps you :)

-RageD
 
0
•••
thanks for good tutorial
 
0
•••
Sure, glad to be of some service to the community! :D Please, if anyone finds any holes let me know so I can patch them ;) Hack away at this script lol it's encouraged. Security means a lot on the web :D

-RageD
 
0
•••
Thanks for sharing :D You'll want to make sure you sanitize the cookie data sent as well as the username and password variables prior to sending to prevent sql injections.

I haven't tested it but passing a password variable to this script as:

Code:
null' OR id='1

would complete the sql query as:

Code:
SELECT * FROM users WHERE name='admin' AND pass='null' OR id='1' LIMIT 1;

Cheers,

Jay
 
0
•••
I would certainly contest this being secure.

You should NEVER put passwords in a cookie even if you MD5 it. If someone sees you have MD5'd something they can find out what you have MD5's quite easily (within a couple of hours) on any modern PC. And working out it is MD5'd is very easy considering the length of an MD5'd string.

As you are providing the username and password MD5'd in the cookie any one who manages to cause an MD5 collission can now log into your site when they get the cookie information.

baxter said:
Thanks for sharing :D You'll want to make sure you sanitize the cookie data sent as well as the username and password variables prior to sending to prevent sql injections.

I haven't tested it but passing a password variable to this script as:

Code:
null' OR id='1

would complete the sql query as:

Code:
SELECT * FROM users WHERE name='admin' AND pass='null' OR id='1' LIMIT 1;

Cheers,

Jay

Exactly yet another security hole in this method. The variables should at least be ran through mysql_real_escape_string
 
0
•••
Peter is right. This is far from being secure.

A good authentication system NEVER stores passwords or any sensitive information in cookies, whether they are encrypted or not. Also guys remember when members register on your sites you should always add salt to any encrypted passwords.
 
0
•••
Peter said:
Exactly yet another security hole in this method. The variables should at least be ran through mysql_real_escape_string
I do this quite often. Actually on my latest project I have a whole SQL_Base class with this function laid within it. As mentioned below, I normally add a salt as well as other sorts of encryptions and tests to run through. But I do see where you're coming from with storing passwords in cookies. Because cookies are clear-text, I don't usually use them myself, but they can still be effective.

DomainManDave said:
Also guys remember when members register on your sites you should always add salt to any encrypted passwords.

Good point. On any project I do (mainly sessions, but whatever works) I usually add salts. Not sure why I didn't on this one. Guess I wrote it fairly quickly.

-RageD
 
0
•••
  • The sidebar remains visible by scrolling at a speed relative to the page’s height.
Back