1
votes

First time creating a login system for a webpage and I've been trying to read up about security but unsure if I'm doing it right.

So far I have a username/password stored and the password is hashed with sha256 and a 3 char salt. if the username and password are correct then I make a new session id like this

session_regenerate_id (); 
$_SESSION['valid'] = 1;
$_SESSION['userid'] = $userid;

at every page I check

function isLoggedIn()
{
if(isset($_SESSION['valid']) && $_SESSION['valid'])
    return true;
return false;
}

I use this to check for a correct user

$username = $_POST['username'];
$password = $_POST['password'];
//connect to the database here
connect();
//save username
$username = mysql_real_escape_string($username);
//query the database for the username provided
$query = "SELECT password, salt
    FROM users
    WHERE username = '$username';";
$result = mysql_query($query);
if(mysql_num_rows($result) < 1) //no such user exists
{
  //show incorrect login message
}
//check the password is correct for the username found
$userData = mysql_fetch_array($result, MYSQL_ASSOC);
$hash = hash('sha256', $userData['salt'] . hash('sha256', $password) );
if($hash != $userData['password']) //incorrect password
{
  //show incorrect login message
}
else
{
//setup a new session 
validateUser();
//redirect to the main page
header('Location: main.php');
die();

if its false then they get sent back to the login page. is this secure enough?

in the main page I also have html links

  <li><a href="main.php">Home page</a>

so I need to end the php script on the main page when these links are used?

5
If this is your first login, it is ok. But you should read about login security. There are a lot of things to consider.machineaddict
3 char salt? it would be more secure if was 16 char and each user had there own salt.Lawrence Cherone
What about the rest of the authentication and authorization? How do you actually verify a user’s authentication and what happens when something fails? Please show us the rest of your code.Gumbo
@Gumbo I'm not sure what you mean, I call the isLoggedIn function above to check they are authorised at every page. if it returns false then I use die() and redirect back to the login page.dan

5 Answers

4
votes

Adding to what phpdev said. Even though it looks secure enough, there are a couple of things I'd recommend.

When you want to send a user to some page make sure your script exits and finishes executing, because if there's still some lines they will be executed. Take this for example:

if (!isLoggedIn()){
   header('Location: login.php');
}
//It's wrong to assume that things are safe here
echo $secret_data;

so make sure you add exit(); or die(); after your header() call.

Also when hashing, make sure that you use a unique salt per user, so you need to create an extra column in your users table to store the salt next to the hashed password. It's also highly recommended to use a well tested library for hashing such as PHPass.

If you're running different web services on the same web server using the same domain, like: mysite.com/my_super_awesome_app and mysite.com/my_not_very_awesome_app make sure you either add a prefix to your variable names in the $_SESSION like $_SESSION['app1_valid'] or limit the session cookie to a certain path using session_set_cookie_params()

3
votes

Yes, that looks secure to me. Just make sure you call session_start() before doing anything and be careful with where you are setting $_SESSION['valid']. Make sure that is only set after you have confirmed the they have entered the right username and password.

As for salting, I would suggest a unique salt with about 10 characters for each user. Then hash the result using crypt with the blowfish algorithm (bcrypt). BCrypt is designed so that is is incrementally more expensive to compute the hash, which is important if someone steals your password hashes.

2
votes

Don't forget to require HTTPS from the login form forward, otherwise this is all for nothing.

0
votes

It looks OK for a basic App. There are so many more things you can do. Timers. Dictionary attacks. Login attempt sessions. Search the SO.

function is_customer_logged_in() {
    if($_COOKIE['GC_CUST_LOGIN']==1 && $_SESSION["loggedIn"]=="1"){
        return true;
    }else{
        return false;
    }
}

$_SESSION["time"]=time();
setcookie("GC_CUST_LOGIN", 1, ".stackoverflow.com");
$_SESSION["loggedIn"]="1";
$_SESSION["loggedIn_Md5_Hash"]=md5(hash);

You can also insert hashes for the session, checked if logged in and add a number and also use cookies and sessions to force matching after database checks.

0
votes

There are a lot of things to consider with password security. Unfortunately a sha-256 still doesn't beat bcrypt or scrypt (they implement key stretching, salts and a scalable work factor to help as hardware improves).

I'd checkout PHPass by openwall (http://www.openwall.com/phpass/) This is a pretty standard bcrypt library and easy to use.

Like some other people have said, unless your login page is secured via HTTPS, the password can still be sniffed.

I like that you're regenerating the session_id. While in this case it might not matter, it helps prevent session replay or session fixation attacks.

Some other things to consider to make your system more secure in general:

  • Password policy
    • Password length
    • Number + special character
  • Passphrases
    • Might have more entropy if you can ensure words aren't common
  • Banning after failed login attempts
  • Adding two-factor authentication