Jump to content

MD5 and salt


Hooch
 Share

Recommended Posts

I have read MD5 is not secure on it's own. So using "Salt" will help this problem.I was wondering if someone could look to see ifI am using it correctly. The following code would be in the register.php page.

<?PHP//clean functionfunction clean($string){$string = addslashes($string);$string = strip_tags($string);$string = htmlspecialchars($string);$string = trim($string);return $string;}	  if ($_POST[register])   {   $username = clean($_POST['username']);  $password = clean($_POST['password']);  $a = $password;  $salt = 'e$+i7*'; //can be anything random  $hash = md5($a.$salt);  $password = $hash;  $update = mysql_query("UPDATE users SET password = '$password'  WHERE username = '$logged[username]'");   //rest of code?>

How does that look??Thank you.

Link to comment
Share on other sites

if the hacker was able to learn your salt then your salt becomes useless because oyu are using the same one for every user.Having a different salt for each user is a better idea. Maybe the first 4 letters of their last name for example

Link to comment
Share on other sites

shouldn't be, is it only the logged in member's last name or is it a list of all members?As long as you keep what the salt is to yourself it will be next to impossible for a hacker to figure it out.

Link to comment
Share on other sites

It will be a list of all members. The site is for a local Artists group. So a lot of personal info will be shown. Name, address, phone etc. Mind you only members will be allowed to join the site. I will have the register.php page pw protected.

Link to comment
Share on other sites

Salts are used to avoid dictionary attacks on a database. If someone gets access to your database, and has a list of all of your hashed passwords, then they can use a program to generate hashes for common words (like a dictionary) and compare all the hashes to find the password that produced them. So when you include a salt in the mix, it gets around that. It's safe to keep your salt in the database as well, as long as the algorithm to generate the password is fairly complex.The way I did it, I have the salt be something like this:$salt = sha1($_SERVER['REMOTE_ADDR'] . time());So it's a sha1 hash of the user's IP plus the time they registered. So I encrypt the password, and mix up the salt and the hashed password into another hash.

$password = sha1($_POST['password']);$db_pw = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));

And then I store the $db_pw and $salt in the database. When I check the password when they log in, I do the same thing. Get the salt and password from the database, generate a $db_pw with what they entered and the salt, and see if it matches the password from the database. In that example, the $db_pw is a hash of the first 20 characters of the hashed password, then the first 20 characters of the hashed salt, then the last 20 characters of the hashed password, then the last 20 characters of the hashed salt.

Link to comment
Share on other sites

Wow, thanks guy! This would be a good way to pw protect a page too. But if the $salt has the users ip and time of registration, when he/shelogs in 5 days later the pw will now be different to the db one, correct?

Link to comment
Share on other sites

Right. You store the salt in the database so you can keep using the same salt later on, you just get it from the database. The security lies in the way you create the database hash. Even if someone has the salt, they won't know how to use it to generate the hash so a dictionary attack wouldn't work. You probably want to do something more then just this:$db_pw = sha1($password . $salt);Because that would probably be the first thing to check. Use substrings, or duplicate the password and salt a bunch of times or mix md5 and sha1 or something like that to make it a little more complex.

Link to comment
Share on other sites

  • 1 month later...

I had some time to start a secure registration. Guy, could you please have a look? And maybe let me know how I am doing?Thank you,Hooch(Simplified for review)

<?php session_start();ob_start(); include "includes/config.php";  setcookie("server", $_SERVER['REMOTE_ADDR']); setcookie("time", time()+(60*60*24*5)); $salt = sha1($server . $time);  if ($_POST[register])   {   include 'includes/clean.php';  $server = $_POST['server'];  $time = $_POST['time'];  $salt = $_POST['salt'];    $username = clean($_POST['username']);  $password = clean($_POST['password']);  $password = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));	    $query = mysql_query("INSERT INTO users ( `id`, `server`, `time`, `salt`, `level`, `username`, `password`, `firstname`, `lastname`, `question`, `answer`, `email`, `website`, `city`, `province`, `zip`, `bio`, `online`) VALUES ('', '$server', '$time', '$salt', '$level', '$username', '$password', '$firstname', '$lastname', '$question', '$answer', '$email', '$website', '$city', '$province', '$zip', '$bio', '$online')")or die(mysql_error());   echo "<center>You have successfully registered!<br>";   }   else   {   //Form goes here  }?>

Link to comment
Share on other sites

I'm not sure why you are getting $server, $time, and $salt from $_POST. You probably want to just create them yourself instead of relying on them being sent. Also, if you are storing the IP in a cookie for security reasons, then you probably want to hash it. Someone could move the cookies to another computer and automatically login by just changing the IP in the cookie. If the IP is hashed, they won't know how to change it. Maybe something like setcookie("server", sha1(md5(sha1($_SERVER['REMOTE_ADDR'])))); The only other issue is how to generate the salt, right now you are getting it from $_POST but it would have to be generated someohow. Also, you haven't hashed the password (unless the clean function does that). In order to generate the password for the database, you will want to hash both the password and the salt using sha1 since you are getting the first/last 20 characters of each. sha1 is a 40-character hash. Other then that, make sure that all of the values in the query are going to be safe from SQL injection.

Link to comment
Share on other sites

I got rid of the cookies.I thought the password was hashed,and also I thought I generated the salt. See code below where I think the hash and salt are...

<?php session_start();ob_start(); include "includes/config.php";  $server = $_SERVER['REMOTE_ADDR']; $time = time()+(60*60*24*5);  //---------------------- Generation of Salt?  ---------------------  $salt = sha1($server . $time);  if ($_POST[register])   {   include 'includes/clean.php';     $username = clean($_POST['username']);  $password = clean($_POST['password']);  //---------------------------  Hash?  ----------------------------	    $password = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));	    $query = mysql_query("INSERT INTO users ( `id`, `server`, `time`, `salt`, `level`, `username`, `password`, `firstname`, `lastname`, `question`, `answer`, `email`, `website`, `city`, `province`, `zip`, `bio`, `online`) VALUES ('', '$server', '$time', '$salt', '$level', '$username', '$password', '$firstname', '$lastname', '$question', '$answer', '$email', '$website', '$city', '$province', '$zip', '$bio', '$online')")or die(mysql_error());    echo "<center>You have successfully registered!<br>";   echo "<a href=\"login.php\" class=\"members\">Click to login</a></center>";   }   else   {   //Form here  }?>

FYI my clean.php is

function clean($string){$string = mysql_real_escape_string($string);$string = trim($string);return $string;}

I'm also curious if it's more secure to save $server, $salt, and $time in another table oreven another db? Thank you for your time Guy.

Link to comment
Share on other sites

Whoops, I didn't see where the salt was created. Storing things in separate databases doesn't really provide any extra security. I don't think you even need to save the $server and $time, you just need to save the hashed salt and the hashed password. Make sure to hash the password before you create the database password:$password = sha1($_POST['password']);

Link to comment
Share on other sites

okay, I think the register is done.

session_start();ob_start(); include "includes/config.php";  $server = $_SERVER['REMOTE_ADDR']; $time = time()+(60*60*24*5); $salt = sha1($server . $time);  if ($_POST[register])   {   include 'includes/clean.php';     $username = clean($_POST['username']);  $password = clean($_POST['password']);  $password = sha1($password);  $password = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));	    $query = mysql_query("INSERT INTO users ( `id`, `server`, `time`, `salt`, `level`, `username`, `password`, `firstname`, `lastname`, `question`, `answer`, `email`, `website`, `city`, `province`, `zip`, `bio`, `online`) VALUES ('', '$server', '$time', '$salt', '$level', '$username', '$password', '$firstname', '$lastname', '$question', '$answer', '$email', '$website', '$city', '$province', '$zip', '$bio', '$online')")or die(mysql_error());    echo "<center>You have successfully registered!<br>";   echo "<a href=\"login.php\" class=\"members\">Click to login</a></center>";   }   else   {   //Form here  }

But the login is not working. My hash is somehow incorrect.

if ($_POST['login']) { $info = mysql_query("SELECT * FROM users WHERE username = '$username'") or die(mysql_error()); $data = mysql_fetch_array($info);include 'includes/clean.php'; $username = clean($_POST['username']);$password = clean($_POST['password']);$server = $data['server'];$time = $data['time'];$salt = sha1($server . $time);$password = sha1($password);$password = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));    if($data['password'] != $password) { echo "<center><br><br><span class=\"black-medium\">Incorrect username or password!</span><br><br>"; echo "<a href=\"login.php\" target\"_self\" class=\"members\">Back</a><br><br><br>"; }else{ echo ("<meta http-equiv=\"Refresh\" content=\"2; URL=login.php\"/><center>Thank You! You will be redirected</center>");echo ("<br><br>"); } }

I would love some help. Thank you.

Link to comment
Share on other sites

You are creating a new salt. You need to use the same salt they originally registered with, because that's how you created the database hash. If you use a new salt with a new timestamp, the hash will be different. So get the salt out of the database and recreate the hash with that.

Link to comment
Share on other sites

I replaced

$server = $data['server'];$time = $data['time'];$salt = sha1($server . $time);

with

$salt = $data['salt'];

The passwords are not matching yet.

if ($_POST['login']) { $info = mysql_query("SELECT * FROM users WHERE username = '$username'") or die(mysql_error()); $data = mysql_fetch_array($info);include 'includes/clean.php'; $username = clean($_POST['username']);$password = clean($_POST['password']);$salt = $data['salt'];//The problem must be in here????$password = sha1($password);$password = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));

Link to comment
Share on other sites

Well, there's not much of a difference. Here is the algorithm to produce the password and salt when someone registers:

$server = $_SERVER['REMOTE_ADDR']; $time = time()+(60*60*24*5); $salt = sha1($server . $time);  if ($_POST[register])   {   include 'includes/clean.php';     $username = clean($_POST['username']);  $password = clean($_POST['password']);  $password = sha1($password);  $password = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));

And from the login:

$info = mysql_query("SELECT * FROM users WHERE username = '$username'") or die(mysql_error()); $data = mysql_fetch_array($info);include 'includes/clean.php'; $username = clean($_POST['username']);$password = clean($_POST['password']);$salt = $data['salt'];//The problem must be in here????$password = sha1($password);$password = sha1(substr($password, 0, 20) . substr($salt, 0, 20) . substr($password, 19, 20) . substr($salt, 19, 20));

In both cases, you are cleaning the password, then hashing it, then combining it with the salt. If you are using the same salt, then it should produce the same results. If you want, you can give both of these algorithms the same set of data (obviously the register algorithm would go first because it makes the salt) and make sure that they produce the same thing, but it doesn't look like there is a problem here. Are you changing the salt at any point? Or try deleting the data from the database and starting over with new data.

Link to comment
Share on other sites

The salt is the same.I echo out all the info on the login page (for my testing purposes).

echo "posted pw = ".$password." DB pw = ".$data['password']."<BR/>";echo "posted name = ".$_POST['username']." DB name = ".$data['username']."<BR/>";echo "DB salt = ".$data['salt']." login page salt = ".$salt;

The password seems to be the only difference here.I just checked the difference in the passwords. (once hashed)After login page, hashed pw = db2e637a0ce0bcc946372ed056364cb081af264fThis is the Database pw ==== 320b7b2cf3288c5dfe8b05041fa88314 It's 14 characters less

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...