Thursday, April 21, 2011

session tracking for users

I want to make it hard for a hacker to get my users information. I will use this method I found on the page I mentioned yesterday.
http://phpsec.org/projects/guide/4.html
This page also uses this great article about securing sessions:
http://shiflett.org/articles/the-truth-about-sessions

First I will check to see if the user identifier is stored in the session. If it is then they are logged in since I will only set this variable after they successfully enter their user name and password. When they login successfully I store the IP address and their browser agent and a secret string of text that can be the same for all users or I could use a combination of username and random characters. This second identifier will be passed in the URL so the attacker would need more than just the sessionid to impersonate them. Is this secure?
Then a hacker will have to steal the session_id and impersonate them and have the same IP address and browser agent string converted to a sha1 fingerprint and store it in the url. So this would be an example:
sha1("Mozilla/5.0 GeckoSECRET_PHRASE78.0.23.128")
this is: 3fb195ec6fe52981918b9065b8362a0efed8858f
then when you are logged in you would be at: http://example.com/admin.php?secret_fingerprint=3fb195ec6fe52981918b9065b8362a0efed8858f
This script can be included in any page. I call it validate_login.php
if(!isset($_SESSION)) session_start();
//starts the database connection
require_once("includes/db.php");
//stores the log function
require_once("includes/functions.php");
$phpself = $_SERVER['PHP_SELF'];
//the user_identifier will be a 13 character random string of text like DA3591BAC915 that is stored for each user to identify them with something besides the primary key
if(isset($_SESSION['USER_IDENTIFIER'])){
if ($_GET['secret_fingerprint'] != sha1($_SERVER['HTTP_USER_AGENT'] . "SECRET_PHRASE" . $_SERVER['REMOTE_ADDR'])){
/* Make them login again */
include('login.php');
exit();
}
} else if(isset($_POST['submitlogin'])){
$user = mysql_real_escape_string($_POST['user']);
$password = sha1(mysql_real_escape_string($_POST['password']));

//authenticate user
$sql = "SELECT user_identifier FROM user WHERE user = '$user' AND password = '$password'";

$result = @mysql_query($sql);
if(!$result) {echo "There was an error";log(mysql_error($con)." sql: $sql ");exit();}
if(mysql_num_rows($result) == 0){echo "You need to user the right user or password";include('login.php'); exit();}
$row = @mysql_fetch_array($result);
$_SESSION['USER_IDENTIFIER'] = $row[0];

//only pass this in the url so it has to exist in a GET parameter for the user to be allowed to stay logged in
$secret_fingerprint = sha1($_SERVER['HTTP_USER_AGENT'] . "SECRET_PHRASE" . $_SERVER['REMOTE_ADDR']);

//send them to the page that requested to login
header('Location: ' . $_SERVER['PHP_SELF'] . '?secret_fingerprint='.$secret_fingerprint);
exit();
} else {
//they aren't logged in yet : show the login form here
include('login.php');
exit();
}

Here is an example page that requires the use of above authentication plus has a logout link and a link to another page. When we go to another page we have to include the secret finger print that has their IP address and browser hashed with an sha1 hash or they will not be authenticated and will have to log in again.
This page is admin.php
<?php
include('validate_login.php');
?>
<h1>You are logged in now</h1>
<a href="logout.php?logout=1&to=<?php echo $phpself;?>">Log off</a><br />
Go to another secure page on the <a href="anotherpage?secret_fingerprint=<?php $_GET['secret_fingerprint'];?>">site</a>.


This also has a logout link that logs the user out. Here is a good logout script:
logout.php
<?php
if(!isset($_SESSION)) session_start();
if(isset($_GET['logout'])){
session_destroy();
unset($_SESSION);
$to = $_GET['to'];

//send them to the page they were being sent to
header('Location: http://'.$_SERVER['SERVER_NAME'].':/'.$to);
exit();
}


Here is the login script login.php:
<form action="<?php echo $phpself;?>" method="post">
<p><label>Email<br /><input type="text" value="<?php if(isset($_POST['user'])) echo $_POST['user'];?>" name="user"></label></p>
<p><label>Password<br /><input type="password" name="password"></label></p>
<p><label><input type="checkbox" name="rememberme"> Remember Me</label></p>
<input type="submit" value="Log In" name="submitlogin"></p>
</form>
<a href="#">Lost your password?</a>


If you need a registration script just leave a comment.

No comments: