Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP session var enough for user auth?

Scenario:

  • After a user has logged in, a session variable is set confirming their login.
  • At the top of every page, login session variable is confirmed valid
  • If it's not, they're booted out.
  • No persistent cookies are used, only session

Question:

Is this a strong enough security measure by itself, or should I

  • Set two session variables to validate eachother and/or
  • Implement database/hash validation
  • ...?

========

(Incidentally, while I was researching this question, this wiki is a fantastic read.)

like image 683
Ben Avatar asked Dec 21 '22 21:12

Ben


2 Answers

It is enough to store just user login (or user id) in the session.

To prevent session fixation/hijacking everything you need is just to implement simple algorythm (pseudocode):

if (!isset($_SESSION['hash']) {
    $_SESSION['hash'] = md5(!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua');
} else if ($_SESSION['hash'] != md5(!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua')) {
    session_regenerate_id();
    $_SESSION = array();
    $_SESSION['hash'] = md5(!empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua');
}

You could move the hash calculation into some function to prevent of duplication, i've just shown a sketch of possible protection.

This is how I implemented this kind of protection in my kohana session class:

abstract class Session extends Kohana_Session
{
    public function read($id = null)
    {
        parent::read($id);

        $hash = $this->calculateHash();
        $sessionHash = $this->get('session_fixation');

        if (!$sessionHash) {
            $this->set('session_fixation', $hash);
        } elseif ($sessionHash != $hash) {
            $this->regenerate();
            $_SESSION = array();
            $this->set('session_fixation', $hash);
        }
    }

    private function calculateHash()
    {
        $ip = !empty($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
        $ua = !empty($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : 'no ua';
        $charset = !empty($_SERVER['HTTP_ACCEPT_CHARSET']) ? $_SERVER['HTTP_ACCEPT_CHARSET'] : 'no charset';
        $ip = substr($ip, 0, strrpos($ip, '.') - 1);
        return md5($ua . $ip . $charset);
    }
}
like image 167
zerkms Avatar answered Dec 24 '22 11:12

zerkms


Don't try to write your own session scheme, PHP will do it better.

yes you can add more information to your $_SESSION to help prevent session hijacking

for example I generate a fingerprint by combining a secret phrase or random data with the user agent and the session_id() and hash it all. To hijack a session the user would need to figure out a valid session_id, and the hash of the fingerprint. it will look like this. This is a good read

$_SESSION['fingerprint'] = md5('somethingSecret' . $_SERVER['HTTP_USER_AGENT']. session_id());

then you would validate the session like

$check_print = md5('somethingSecret' . $_SERVER['HTTP_USER_AGENT']. session_id());

if($check_print != $_SESSION['fingerprint'] || $_SESSION['authenticated']){ 
    //invalid session
}
like image 23
Brian Avatar answered Dec 24 '22 11:12

Brian