PHP Login System

Associate
Joined
14 Nov 2006
Posts
2,057
Location
UK
Hi guys, I've been working on a login system for an assignment and I've hit a bit of a wall. Tried lots of things myself but I can't get it working, hoping someone more experienced could shed some light on it!

I haven't made the registration part yet so I've just inserted a user manually into the database.

I used several tutorials and guides to do what I've done so far, and it works but I want to add password hashing with salt into it as I've read this is much better than just hashing the password on it's own.

My login function looks like this at the moment which works but it would just use the same string appended to every password.

PHP:
function validateUser($username, $password) {
		
$P_SALT = 'qWI-lXh.5V##cx$:)|%]ScM3fk87Iuf-S^Ula>%Qv:jv^mm|O,T_=7I/`)~c@£e=';
		
   $mysql = new mysql();
   $ensure_credentials = $mysql->verifyUsernamePass($username, hash('sha512', $password . $P_SALT));
		
       if($ensure_credentials) {
           $_SESSION['status'] = 'authorized';
	       header("location: index.php");
	} else return "Please enter a correct username and password";		
}

And the database query part:

PHP:
function verifyUsernamePass($username, $password) {
			
$query = "SELECT *
	      FROM admins
	      WHERE username = ? AND password = ?
	      LIMIT 1"; //limit to 1
				
    if($stmt = $this->conn->prepare($query)) {
    $stmt->bind_param('ss', $username, $password);
    $stmt->execute();
			
        if($stmt->fetch()) {
            $stmt->close();
            return true;
        }
    }	
}


I made a small function to generate a random string but I'm not sure how to implement it into what I've already done - I tried storing the salt in the database with the username and password, then modifying the query to get that with the username and password but I just got errors with it.

PHP:
$password = "admin";

function makeSsalt() {
  list($usec, $sec) = explode(' ', microtime());
  return (float) $sec + ((float) $usec * 100000);
}
	mt_srand(makeSalt());
	$randVal = mt_rand();
	
	$newPass = $randVal . $password;
	$encryptPass = hash('sha512', $newPass);

If anyone has any pointers, they would be greatly appreciated! I'm not very experienced with PHP yet. Thanks!
 

fez

fez

Caporegime
Joined
22 Aug 2008
Posts
25,806
Location
Tunbridge Wells
The general idea of a salt is to help protect against rainbow table attacks (huge lookup of hashed words). If someone gets your database of username / passwords and they are not salted then they can simply run all your user credentials against the rainbow table to crack any simple ones very quickly.

The salt is there to append a string of random characters to the password that would never appear in a standard rainbow lookup. If you use the same salt for every user then if someone gets hold of the salt and user /pass info, they can simply generate a new rainbow table taking into account the salt.

The same is true for a per user salt but as you can imagine, generating a new table for every single user would be massively time consuming and still not guaranteed to work whereas in the other cases you are probably going to get lots of matches on weak passwords even if some of the stronger ones remain secure. With the per user salt, they can only hit the ones they generate rainbow tables for whereas the single salt for everyone means that they will simply run every user record over with the rainbow table and the weak ones will crack first.

To integrate that into a login system you could do the following.

Save unique salt, username, password to the db. Password is hashed using a reproducible algorithm (not incorporating random chars, timestamps etc)

User tries to login with username and password.

Retrieve account via the username.

Using the same hashing algorithm as when you generated the hashed password, take the salt from the db and the password from the user submitted form and hash them in the same way (same order etc).

If the hash of the user submitted password + salt matches the password you retrieved from the db, the user has entered the correct username password.
 
Last edited:
Associate
OP
Joined
14 Nov 2006
Posts
2,057
Location
UK
The general idea of a salt is to help protect against rainbow table attacks (huge lookup of hashed words). If someone gets your database of username / passwords and they are not salted then they can simply run all your user credentials against the rainbow table to crack any simple ones very quickly.

The salt is there to append a string of random characters to the password that would never appear in a standard rainbow lookup. If you use the same salt for every user then if someone gets hold of the salt and user /pass info, they can simply generate a new rainbow table taking into account the salt.

The same is true for a per user salt but as you can imagine, generating a new table for every single user would be massively time consuming and still not guaranteed to work whereas in the other cases you are probably going to get lots of matches on weak passwords even if some of the stronger ones remain secure. With the per user salt, they can only hit the ones they generate rainbow tables for whereas the single salt for everyone means that they will simply run every user record over with the rainbow table and the weak ones will crack first.

To integrate that into a login system you could do the following.

Save unique salt, username, password to the db. Password is hashed using a reproducible algorithm (not incorporating random chars, timestamps etc)

User tries to login with username and password.

Retrieve account via the username.

Using the same hashing algorithm as when you generated the hashed password, take the salt from the db and the password from the user submitted form and hash them in the same way (same order etc).

If the hash of the user submitted password + salt matches the password you retrieved from the db, the user has entered the correct username password.

Thanks for the information and good post!

I think that's what I tried but I couldn't get it to work, I added a new database field, and inserted the generated salt, and updated the hashed password with it. Altered the query to get that as well - I think that's probably where I was going wrong. I was getting an error related to the extra variable I put in there.

Was something like this if I remember:

function verifyUsernamePass($username, $salt, $password) {

and,

$query = "SELECT *
FROM admins
WHERE username = ? salt = ? AND password = ?
LIMIT 1"; //limit to 1

if($stmt = $this->conn->prepare($query)) {
$stmt->bind_param('sss', $username, $salt, $password);
$stmt->execute();


Then I would edit the validate function to match, but I just got errors when trying to login then.

fez has given you some good info, but I sort of question the logic in writing this yourself. Are you not allowed to use a library?

I'm not sure, but I can't see why not, I will ask. Are there any particular ones worth taking a look at? the assignment is for a client so it would be good to present them with something more robust.

I haven't done a right lot of PHP in the past but hopefully getting there!

Thanks guys :)
 

fez

fez

Caporegime
Joined
22 Aug 2008
Posts
25,806
Location
Tunbridge Wells
Basically there are a tonne of security implications with auth systems and because its the gateway to your application, its very important. Well written third party libraries take those concerns into consideration and provide stuff like password reset / change mechanisms which are a bit of a faff too.

Depending on what the project is for I would consider it. If its an assignment to build a cms with login system then you might be expected to code it yourself.

From the code above I would say you are getting one part wrong.

How is the salt passed to verifyUsernamePass()?

The user should never be aware of the salt. They give you their username / password and you take the username to retrieve the record for the user.

Once you have that record, you take the salt from the record and perform the same hashing algorithm on the user provided password and the records salt value. This is then compared to the records password (which is a hash of course).

If the records password hash matches the hash of the user provided password and records salt you have a valid login request.

If you want to give users feedback on what went wrong (another topic on security) you can let the user know if their username or password was wrong quite easily. If you find a user record for the username but the password validation fails, you know there is an account for them and that the password was the issue.
 
Associate
OP
Joined
14 Nov 2006
Posts
2,057
Location
UK
Yeah, that's what I want to do. I'd generate the salt when they register and put it with the password.

I have it setup so when a user enters their username and password into the form, it goes to the validateUser function, which at the moment uses the same salt:

PHP:
function validateUser($username, $password) {
		
    $P_SALT = 'qWI-lXh.5V##cx$:)|%]ScM3fk87Iuf-S^Ula>%Qv:jv^mm|O,T_=7I/`)~c@£e=';
		
    $mysql = new mysql();
    $ensure_credentials = $mysql->verifyUsernamePass($username, hash('sha512', $password . $P_SALT));
		
    if($ensure_credentials) {
	$_SESSION['status'] = 'authorized';
	    header("location: index.php");
    } else return "Please enter a correct username and password";
		
}

Then it goes to mysql.php:

PHP:
<?php

require_once 'includes/constants.php';

class mysql {
	private $conn;
	
	function __construct() {
		$this->conn = new mysqli(DB_SERVER, DB_USER, DB_PASSWORD, DB_NAME) or 
					  die('There was a problem connecting to the database.');
	}
	
	function verifyUsernamePass($username, $password) {
				
		$query = "SELECT *
				FROM admins
				WHERE username = ? AND password = ?
				LIMIT 1"; //limit to 1 for security
				
		if($stmt = $this->conn->prepare($query)) {
			$stmt->bind_param('ss', $username, $password); //username and password are both strings
			$stmt->execute();
			
			if($stmt->fetch()) {
				$stmt->close();
				return true;
			}
		}	
	}
}

Thanks for the help so far!
 

aln

aln

Associate
Joined
7 Sep 2009
Posts
2,076
Location
West Lothian, Scotland.
I'm not sure, but I can't see why not, I will ask. Are there any particular ones worth taking a look at? the assignment is for a client so it would be good to present them with something more robust.

I haven't done a right lot of PHP in the past but hopefully getting there!

Thanks guys :)

If this isn't a uni thing / examination then you should probably be using a library, there may be exceptions where you need to vet every line of code but I very much doubt you're one of them. If it is a uni thing you should ask your professor right away, he'll likely allow it being that he's planning to ship the thing out to a 3rd party.

I was hoping fez or someone else would have answered the go to library, I think it's PHPass, but I haven't written anything new in quite some time. Normally I would recommend a framework too, which will have a login system combined. Again my experience doesn't lend itself to recommendations on this, but you'll want to start with someone popular.

You shouldn't follow my advice if you're quite some way through, but I presume you'd work on user access control in fairly early development so you might want to think about reconsidering using pure PHP.

Are you working on a prototype or the final version of something that's going live?
 
Last edited:
Associate
OP
Joined
14 Nov 2006
Posts
2,057
Location
UK
If this isn't a uni thing / examination then you should probably be using a library, there may be exceptions where you need to vet every line of code but I very much doubt you're one of them. If it is a uni thing you should ask your professor right away, he'll likely allow it being that he's planning to ship the thing out to a 3rd party.

I was hoping fez or someone else would have answered the go to library, I think it's PHPass, but I haven't written anything new in quite some time. Normally I would recommend a framework too, which will have a login system combined. Again my experience doesn't lend itself to recommendations on this, but you'll want to start with someone popular.

You shouldn't follow my advice if you're quite some way through, but I presume you'd work on user access control in fairly early development so you might want to think about reconsidering using pure PHP.

Are you working on a prototype or the final version of something that's going live?

It is for uni yeah, I will ask when I next seem him. I can't see it being problem if I use some existing system, which would be better for the client (more secure and feature rich etc). I haven't even started thinking about password resets and stuff yet!

All I've done in the login form so far, which gets a user to an admin page (which is pretty much blank at the moment). So it wouldn't be a massive loss to move over I don't think.

He'd probably like it if I did my own, but what I could do is use a library for the main but hand my own one in as well to show that I gave it ago at least.
 

aln

aln

Associate
Joined
7 Sep 2009
Posts
2,076
Location
West Lothian, Scotland.
It is for uni yeah, I will ask when I next seem him. I can't see it being problem if I use some existing system, which would be better for the client (more secure and feature rich etc). I haven't even started thinking about password resets and stuff yet!

All I've done in the login form so far, which gets a user to an admin page (which is pretty much blank at the moment). So it wouldn't be a massive loss to move over I don't think.

He'd probably like it if I did my own, but what I could do is use a library for the main but hand my own one in as well to show that I gave it ago at least.

I actually got a fail on my first attempt of what was essentially a PHP module for submitting code which was not to the professors expectations. This was after working as developer (using php) for several years. I like to think the guy was just a **** but thems the breaks.

Ask and be specific, but don't waste your time doing anything you don't need to do either. Thats my advice. :)
 
Associate
OP
Joined
14 Nov 2006
Posts
2,057
Location
UK
I actually got a fail on my first attempt of what was essentially a PHP module for submitting code which was not to the professors expectations. This was after working as developer (using php) for several years. I like to think the guy was just a **** but thems the breaks.

Ask and be specific, but don't waste your time doing anything you don't need to do either. Thats my advice. :)

Thanks for the advice, I will definitely ask when I see him on Monday!

I'd obviously like to get my own version working (would get more marks too), but I can see the benefits of using a something like PHPass after doing some reading.
 

aln

aln

Associate
Joined
7 Sep 2009
Posts
2,076
Location
West Lothian, Scotland.
Thanks for the advice, I will definitely ask when I see him on Monday!

I'd obviously like to get my own version working (would get more marks too), but I can see the benefits of using a something like PHPass after doing some reading.

Depends how they mark it. If they mark it based on a feature set, the extra work gets you nothing. If the guy actually cares that you can code and understand the problems, it might.

I definitely see the benefit in knowing how to roll your own though, no argument there. Especially as you should be able to validate whether or not the library you're choosing actually does the job well. :p
 
Associate
OP
Joined
14 Nov 2006
Posts
2,057
Location
UK
We've got to meet certain criteria in the whole assignment, the user login part is just one of those. Seen a few people just using what dreamweaver gives you. I think using a library will be okay, but I will make sure before putting effort into integrating one.

Seems to be quite a lot when I google, I have just found another indepth tutorial that I will look at tomorrow which have salts and password resets included. See what I can learn from that!
 

aln

aln

Associate
Joined
7 Sep 2009
Posts
2,076
Location
West Lothian, Scotland.
We've got to meet certain criteria in the whole assignment, the user login part is just one of those. Seen a few people just using what dreamweaver gives you. I think using a library will be okay, but I will make sure before putting effort into integrating one.

Seems to be quite a lot when I google, I have just found another indepth tutorial that I will look at tomorrow which have salts and password resets included. See what I can learn from that!

The reason I told you not to bother doing extra work is more to do with you running out of time and getting a worse mark because you miss features, rather than what you're actually learning. By all means fit it all in if you can but make sure you make and meet your priorities.

I know I'm really responding to like 3 quotes back but I'm crap at forums. :p
 
Associate
OP
Joined
14 Nov 2006
Posts
2,057
Location
UK
The reason I told you not to bother doing extra work is more to do with you running out of time and getting a worse mark because you miss features, rather than what you're actually learning. By all means fit it all in if you can but make sure you make and meet your priorities.

I know I'm really responding to like 3 quotes back but I'm crap at forums. :p

Yeah of course, I'm going to meet all the requirements, I just want to do a good job of them. What I have meets them, but I wanted to make it more secure with the salts being used, rather than just hashing the password on it's own.

I'm getting going with the other parts today, so I don't spend ages banging my head over the password stuff!
 
Associate
Joined
15 Dec 2008
Posts
718
Just going back to your initial post since no-one seems to have picked up on it yet; possibly the reason it was throwing errors - typo-ed function name (makeSsalt):

PHP:
function makeSsalt()

mt_srand(makeSalt())

(Useless now you're going down a different route but possibly somewhat reassuring to you)
 
Back
Top Bottom