bici
bici

Reputation: 47

Is my simple user authentication system secure enough?

I've been working on this authentication system for user login and would appreciate some feedback.

My idea is this. Use sessions and one additional cookie. Session cookie and additional cookie work together. In my Login class, after i check if the username and password are correct, i call sessionStart method and send user's id from database:

public function sessionStart($id) {
    session_start();
    $cookieName = "RagingBull";
    $hash = $this->loginHash($id);
    setcookie($cookieName, $hash);
}

In my sessionStart method, a loginHash method is called. loginHash method creates hash and links together session cookie and additional cookie.

public function loginHash($id) {
    $timeStamp              = time();
    $randNumber             = mt_rand(0, 1000);
    $userId                 = $id;
    $_SESSION['timeStamp']  = $timeStamp;
    $_SESSION['randNumber'] = $randNumber;
    $_SESSION['userId']     = $id;
    $userAgent              = $_SERVER['HTTP_USER_AGENT'];
    $salt                   = "On the Waterfront";
    $ipFrag                 = substr($this->getUserIP(), 0, 5);
    $forHash                = $timeStamp.$salt.$userId.$ipFrag.$randNumber.$userAgent;
    $hash                   = md5($forHash);
    return $hash;

}

For creating a hash value, i use

I save some values in session cookie so that i can use them later when creating hash for comparison. After that, we go back to sessionStart method, and create additional cookie with returned hash value, and then user is logged in.

For authentication, i have Session class.

class Session {

public function __construct() {

    session_start();
    // checks to see if all the cookies are there
    if(!isset($_SESSION['userId']) || !isset($_COOKIE['RagingBull'])) {
        header("Location:http://localhost/login.php");
    }

    //create hash for comparison
    $hash = $this->loginHash();

    //if hashes are not the same, redirect
    if(strcmp($hash, $_COOKIE['RagingBull']) !== 0) {
        header("Location:http://localhost/login.php");
    }
}

public function loginHash() {
    $timeStamp  = $_SESSION['timeStamp'];
    $randNumber = $_SESSION['randNumber'];
    $userId         = $_SESSION['userId'];
    $userAgent  = $_SERVER['HTTP_USER_AGENT'];
    $salt       = "On the Waterfront";
    $ipFrag     = substr($this->getUserIP(), 0, 5);
    $forHash    =  $timeStamp.$salt.$userId.$ipFrag.$randNumber.$userAgent;
    $hash       = md5($forHash);
    return $hash;
}

public function getUserIP() {
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $ip = $_SERVER['REMOTE_ADDR'];
    }

    return $ip;
}

}

To use it, i just create instance of Session class. Then, in constructor, after basic checking, there is creation of hash for comparison, i use the timeStamp, userId and randNumber from session cookie which i saved before, and combine them with user agent and ip fragment from user who requested page.

Upvotes: 0

Views: 84

Answers (1)

Scott Arciszewski
Scott Arciszewski

Reputation: 34113

This code does a lot of pointless things insecurely.

  • Using mt_rand() instead of random_int().
  • Using md5($var) instead of hash('sha256', $var)
  • Using md5($password) instead of password_hash() and password_verify()
  • The "login hash" is entirely meaningless.

If you're trying to do persistent authentication (i.e. "remember me" cookies), just implement that.

If you're trying to protect against session attacks, just use TLS (and ensure your session ID is generated from /dev/urandom if you're still on PHP 5) and strict mode. Call session_regenerate_id(true) whenever the user logs in or logs out. Done.

The hashing here adds no value, and you're using tools that were not meant for secure authentication.

Upvotes: 0

Related Questions