Page 1 of 1

Questions about member system like setups

Posted: Thu Jan 15, 2004 2:43 pm
by timhortons
Hi, this is my first official topic here, and I'm just curious about opinions and suggestions regarding member systems.

I recently wrote a members system based on MySQL and PHP. It was probably more complicated than I needed to go, and I'm always adding things to it. But what I am curious about is some validation techniques, as well as session/cookie management. Also, the login process.

As it stands, I have two seperate styles of member login systems, one uses pure sessions, and the other, my most recent work, uses cookies. (I was planning to make a system that uses both in the future for people wary of cookies.)

When you are confronted with the login box, it asks for your username, and your password. The username stays plain text, and the password gets an md5 encryption and is compared to the md5 encrypted password in the database. This way, the password is pretty much always secret. What I want to know about that, is whether that type of encryption is strong enough for most uses, also the login page isn't on a SSL connection. Is it possible someone could "watch" the form for input and snatch the real one before it gets encrypted and compared?

Also, for keeping the session/cookie fairly unique and near impossible for someone to steal, i put in the users "USER_AGENT" string, as well as their IP. So now, each time they visit a locked page, i check the username, and encrypted password against the entries in the database, and then i check the user agent string and IP against their current ones, to help determine if they're coming from the same machine, but like I said, this doesnt work for people with dialup, and probably proxies. So for validation, I was wondering if I should continue trying to determine whether they are coming from the same machine, or whether just comparing the username and encrypted password in the session/cookie is enough.

I think my system is fairly robust, but if you could offer some of your experiance on matters like this, I'd be interested. Extreme security isnt needed for my uses, but some people are more suceptable to attacks from hackers and the like and could be hi-jacked, and then of course, the site that makes use out of my system could become vulnerable to vulgar posts or things of that nature.

Posted: Thu Jan 15, 2004 3:02 pm
by kettle_drum
Well you must remember that if somebody wants to get into your system bad enough - then they are likely to succede. So its unlikely you will ever make it so that its flawless. The aim of encryption is to keep the data secure while it is worth something - i.e. data with more value should be encrypted using stronger techniques.

So if you use this rules for your site things will turn out ok. you dont need immense security checks and extra strong encryption if the value of the data hidden is minimal.

The methods that you are already using are good, and if you want more security then try to mix them together. Compair the username with the session and the IP, the browser id, the users system etc, any bit of info you can get about the machine when it first logs on can be used to ensure that its the same person later on in the session.

With the cooke method you tend to store the username and password in the cookie - now that is a risk, if the password is there with the username - even if it is a md5 hash of it, somebody can still work out the plaintext. So instead of holding the username and password, try holding two randomly generated 32 character numbers that are given to the user when they log in. Store these two numbers in a second table in the database and each time the user loads a page check the two random numbers and if they match you know the user is valid. this will also stop people knowing what the username is if they get hold of the cookie - so its slightly more secure.

Also consider your biggest risk to security...the user.

If the user users a password that is 3 letters long and common, then its easy for a hacker to bruteforce it or guess it. Ensure that users with priveldges have strong passwords - at least 8 chars long using a mixture of upper and lower case and numbers/symbols. Then store the time the user last changed their password and force them to change it every so often - making sure that the new password is no the same as the old or a previous one (store the last 2 or 3 passwords they have used and check them).

Theres just a few ideas. Oh and while your foccusing on your php system make sure your sever is also secure!!

Posted: Thu Jan 15, 2004 3:22 pm
by timhortons
Heh, yeah, great ideas bout the random numbers!

I think i can also work with 'keeping a history' of their past few passwords and then use something like similar_text to help figure out how different their new one is from the last. Time stamps and forcing them to change it every so often is a great suggestion as well. I could probably write up a few functions to force the user to fit in some numbers and letters, and then limit the length to at least 6 characters.

Thanks for the reply! heh, you got me stirring with hundreds of new ideas now :lol:

Anymore comments graciously appreciated too :D

Posted: Thu Jan 15, 2004 3:34 pm
by Unipus
Honestly, if your site is non-sensitive, it sounds to me like you're already going overkill. Your head's in the right place, and some of the suggestions you want to implement are solid, but in particular the IP bit strikes me as excessive. From a usability standpoint, that's trouble. What if I *want* to access a site from multiple computers, or my home and also office, or I'm travelling? That's pretty common. How are you going to authenticate against that? Short answer: you can't, and you're just going to make headaches for your users.

Posted: Thu Jan 15, 2004 5:07 pm
by kettle_drum
Well you would just have a different IP from different locations and so you would be logged out, and would need to log back in again. If anything its a good idea as it ensures the user logs out and doesnt remain logged in at a particular machine so other people can come along and user their account.

Posted: Thu Jan 15, 2004 5:13 pm
by kettle_drum
Have already written a few functions for doing the things i suggested for a cms i was working on. I have them all in a class that deals with passwords, but here are just the functions.

Code: Select all

<?php
   ##--------------------------------------------
   ##LENGTH CHECK FUNCTION
   ##--------------------------------------------
   function length_check($pass, $len){
      if(strlen($pass)<$len){
         return 1;
      }
   }

   ##--------------------------------------------
   ##OLD NEW CHECK FUNCTION
   ##Makes sure the new pass is not the same as the old
   ##--------------------------------------------
   function old_new_check($pass, $old){
      if($old==$pass){
         return '1';
      }
   }

   ##--------------------------------------------
   ##STRONG PASS CHECK FUNCTION
   ##Makes sure the pass is strong - includes numbers/chars/uppercase
   ##--------------------------------------------
   function strong_pass_check($pass){
      if(!preg_match("/(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s)/", $pass)){
         return '1';
      }
   }

   ##--------------------------------------------
   ##NOT USED PASS CHECK FUNCTION
   ##Makes sure the pass has not been used in the last change
   ##--------------------------------------------
   function not_used_pass_check($pass, $uid){
      $check = IO::database_query("SELECT last_password FROM members WHERE uid = '$uid'");
      if(md5($pass)==$check['last_password']){
            return '1';
      }
   }

?>
The NOT USED PASS CHECK FUNCTION gets the last password used by the user from the database using some of my other classes, so be sure to change it.

The reason why all the functions accept variables for things like length is because i pass a variable stored in a config database to it - so that lengths can easily be changed.

In my members table i hold the last_password and password_change to hold the time of the last change. Having changed the password successfully these fields then get updated.

Posted: Thu Jan 15, 2004 6:41 pm
by timhortons
Wow, thanks for sharing, thats great! :D If anyones interested, i could post my members system, it could save some people some time trying to figure out things, hehe 8)

Posted: Fri Jan 16, 2004 2:54 am
by McGruff
Quick note on IP: although IP is usually constant per session, AOL users can have different IPs within a session.

Posted: Sun Jan 18, 2004 3:07 am
by timhortons
Yeah, thanks for that tidbit.

I just finished up a new "password complexity" test function. What do you think?

Code: Select all

$password = "testpswd2625";
$limit = 6;
check_complexity($password,2,2,$limit);

function check_complexity ($pass,$min_nums,$min_chars,$limit)
{
  # If the minimum amount of letters and numbers add up to more than
  # the minimum length of the password, increase the minimum length 
  # of the password.
  if(($min_nums+$min_chars) > $limit)
  {
    $diff = ($min_nums+$min_chars) - $limit;
    $limit = ($limit+$diff);
  }
  
  echo "\nThe password must have at least ".$min_nums." numbers in it.\n";
  echo "\nThe password also needs to have at least ".$min_chars." letters in it.\n";
  echo "\nThe length of the password must be at least ".$limit." characters long.\n";
  
  $len = strlen($pass); // Count starts at '1' instead of '0'
  for($i=0;$i<$len;$i++)
  {
    if(preg_match("/\d+/",$pass[$i]))
	  $nums[] = $pass[$i];
	else
      $chars[] = $pass[$i];
  }
  if($len < $limit)
  {
    echo "\nAttempted Password was too short!";
  }
  elseif(count($nums) < $min_nums)
  {
    echo "\nNot enough numbers in the password!";
  }
  elseif(count($chars) < $min_chars)
  {
    echo "\nNot enough characters in the password!";
  }
  else
    echo "\nPassword <u>is fine</u> with ".count($nums)." numbers, ".count($chars)." characters, and a length of ".$len;
}