The way I designed my roles in php is the following. When a user logs in the code checks whether the user is the moderator.
If he is a simple user, he gets a cookie that isnt requiring to have https. Otherwise, if he is a moderator, I assign a special session like this:
ini_set('session.use_only_cookies',true);
session_start();
//generate pass for the database && session
$pass=microtime().Moderator::generate_salt(30);
//Insert pass
Moderator::insert_moderator($pass);
//Encrypt the pass and give it back to the users session ID
$_SESSION["mod"]=$mod->encrypt_pass($pass);
The code above takes the login time the moderator logs in, attaches a random salt, and inserts or updates the moderators pass depending if the session started or is over (in this case it is the first time, the mod is assigned the session as he logs in).
Also notice that this is the encryption and dycryption alogrithm I use:
public function encrypt_pass($session_id)
{
$session_id=strip_tags($session_id);
$session_id=trim($session_id);
//inititialization vector is being created.- a seed for random encryption and decryption
srand((double)microtime()*10000);
//opens an ecryption algorithm for use.
$this->td=mcrypt_module_open(MCRYPT_RIJNDAEL_256,'',MCRYPT_MODE_CFB,'');
//creates an IV for out encryption. Two parameters: size of IV ti create and method used to create IV
$this->iv=mcrypt_create_iv(mcrypt_enc_get_iv_size($this->td), MCRYPT_RAND);
//get maximum size the algorithm will take.
$this->ks=mcrypt_enc_get_key_size($this->td);
//here teh key is created
$this->keys=substr(sha1(Moderator::generate_salt()),0, $this->ks);
//initialize the algorithm engine using , IV, and key we selected
mcrypt_generic_init($this->td,$this->keys,$this->iv);
//Two parameters, the algorithm resource and the data we actually want to encrypt. returns an incrypted value
$this->ciphertext=mcrypt_generic($this->td,$session_id);
//clean up!! parameter is -- algorithm resource
mcrypt_generic_deinit($this->td);
//end clean up!!
mcrypt_module_close($this->td);
//Goes to the moderators session $_SESSION['$ciphertext']
return $this->ciphertext;
}
public function decrypt_pass($session_id)
{
$session_id=strip_tags($session_id);
$session_id=trim($session_id);
mcrypt_generic_init($this->td, $this->keys,$this->iv);
$plaintext=mdecrypt_generic($this->td,$session_id);
mcrypt_generic_deinit($this->td);
mcrypt_module_close($this->td);
}
This should prevent me from session fixation/hijacking, it would be simply too hard for a hacker to catch the moderators session id, and even if he did, as soon as the moderator makes another request the password resets itself and if he closes the browser the session ends. This leaves the hacker with a small time frame to get the password and pretend to be the moderator.
The question: Is this enough to cope with session hijacking/fixation or should I add any other precautions?
Notice that it is true that the way I use this algorithm slows the requests and responses. But there will be limited number of moderators, no more than 10.
The code updates itself with every request of the moderator,
Weakness of your algorithm is that you don't anyhow identify particular user. You're just putting there time and some random salt. To prevent session/cookie hijacking you need to put into encrypted string as many identification factors as you can. For example, client's os, user-agent, browser version, ip, forwarded ip, etc ... . In this case you will decrypt string that you have sent to user, assuming that only you can decrypt it, because only you have an AES key, and will verify all parameters that you've inserted into encrypted string. Failure of even one factor verification means that probably someone hijacked session and you need to destroy it.
I will advice you to look at Suhosin at http://www.hardened-php.net/suhosin/. This is a PHP plugin that makes everything described above for you. It is transparent and lightweight. When using Suhosin be aware of setting cookies via javascript, because javascript sets unecrypted cookie and though server can't read it.