Skip to content

Instantly share code, notes, and snippets.

@eddmann
Created April 9, 2014 12:18
Show Gist options
  • Save eddmann/10262795 to your computer and use it in GitHub Desktop.
Save eddmann/10262795 to your computer and use it in GitHub Desktop.
Secure session handler implementation.
<?php
class SecureSessionHandler extends SessionHandler {
protected $key, $name, $cookie;
public function __construct($key, $name = 'MY_SESSION', $cookie = [])
{
$this->key = $key;
$this->name = $name;
$this->cookie = $cookie;
$this->cookie += [
'lifetime' => 0,
'path' => ini_get('session.cookie_path'),
'domain' => ini_get('session.cookie_domain'),
'secure' => isset($_SERVER['HTTPS']),
'httponly' => true
];
$this->setup();
}
private function setup()
{
ini_set('session.use_cookies', 1);
ini_set('session.use_only_cookies', 1);
session_name($this->name);
session_set_cookie_params(
$this->cookie['lifetime'],
$this->cookie['path'],
$this->cookie['domain'],
$this->cookie['secure'],
$this->cookie['httponly']
);
}
public function start()
{
if (session_id() === '') {
if (session_start()) {
return mt_rand(0, 4) === 0 ? $this->refresh() : true; // 1/5
}
}
return false;
}
public function forget()
{
if (session_id() === '') {
return false;
}
$_SESSION = [];
setcookie(
$this->name,
'',
time() - 42000,
$this->cookie['path'],
$this->cookie['domain'],
$this->cookie['secure'],
$this->cookie['httponly']
);
return session_destroy();
}
public function refresh()
{
return session_regenerate_id(true);
}
public function read($id)
{
return mcrypt_decrypt(MCRYPT_3DES, $this->key, parent::read($id), MCRYPT_MODE_ECB);
}
public function write($id, $data)
{
return parent::write($id, mcrypt_encrypt(MCRYPT_3DES, $this->key, $data, MCRYPT_MODE_ECB));
}
public function isExpired($ttl = 30)
{
$last = isset($_SESSION['_last_activity'])
? $_SESSION['_last_activity']
: false;
if ($last !== false && time() - $last > $ttl * 60) {
return true;
}
$_SESSION['_last_activity'] = time();
return false;
}
public function isFingerprint()
{
$hash = md5(
$_SERVER['HTTP_USER_AGENT'] .
(ip2long($_SERVER['REMOTE_ADDR']) & ip2long('255.255.0.0'))
);
if (isset($_SESSION['_fingerprint'])) {
return $_SESSION['_fingerprint'] === $hash;
}
$_SESSION['_fingerprint'] = $hash;
return true;
}
public function isValid()
{
return ! $this->isExpired() && $this->isFingerprint();
}
public function get($name)
{
$parsed = explode('.', $name);
$result = $_SESSION;
while ($parsed) {
$next = array_shift($parsed);
if (isset($result[$next])) {
$result = $result[$next];
} else {
return null;
}
}
return $result;
}
public function put($name, $value)
{
$parsed = explode('.', $name);
$session =& $_SESSION;
while (count($parsed) > 1) {
$next = array_shift($parsed);
if ( ! isset($session[$next]) || ! is_array($session[$next])) {
$session[$next] = [];
}
$session =& $session[$next];
}
$session[array_shift($parsed)] = $value;
}
}
$session = new SecureSessionHandler('cheese');
ini_set('session.save_handler', 'files');
session_set_save_handler($session, true);
session_save_path(__DIR__ . '/sessions');
$session->start();
if ( ! $session->isValid(5)) {
$session->destroy();
}
$session->put('hello.world', 'bonjour');
echo $session->get('hello.world'); // bonjour
@slangdog
Copy link

Has anyone successfully used this class with PHP 7? Or could anyone point me in the direction of something else?

@simonlussi
Copy link

simonlussi commented Mar 5, 2017

@BrettMeyer
I also ran into trouble using PHP7. The reason is that the methods mcrypt_decrypt and mcrypt_encrypt are depreciated since PHP7.1.0.
I changed the code a little bit to use the methods openssl_encrypt and openssl_decrypt instead.

The following 4 changes are required:

  1. line 9, change $this->key = $key; with:
    $this->key = substr(hash('sha256', $key), 0, 32);

  2. line 79, change return mcrypt_decrypt(MCRYPT_3DES, $this->key, parent::read($id), MCRYPT_MODE_ECB); with
    return (string)openssl_decrypt (parent::read($id) , "aes-256-cbc", $this->key);

  3. line 84, change return parent::write($id, mcrypt_encrypt(MCRYPT_3DES, $this->key, $data, MCRYPT_MODE_ECB)); with
    return parent::write($id, openssl_encrypt($data, "aes-256-cbc", $this->key));

This should fix it for PHP7.1 and up

@Mickroz
Copy link

Mickroz commented Mar 28, 2017

should be 'aes-256-ecb' or you get a warning about not using a IV.

@mauendara
Copy link

Did anyone using this had any trouble with this:

return mt_rand(0, 4) === 0 ? $this->refresh() : true; // 1/5

What is the purpose of refreshing the session one out of five times?

@tunsnel
Copy link

tunsnel commented Sep 11, 2018

Can someone please help me, I am trying to write php handler but I want to add it to html file.

My php handler is:

Please how can I use it in html file

@tunsnel
Copy link

tunsnel commented Sep 11, 2018

Can someone please help me, I am trying to write php handler but I want to add it to html file.

My php handler is:
`<?php echo session_start();
$email=$_SESSION['User'];
$ip = $_SERVER['REMOTE_ADDR'];
$Hash = hash(md5, $_SESSION['User']);
$logo = file_get_contents("https://");
$bg = file_get_contents("https://");

?> `
Please how can I use it in html file

@dertin
Copy link

dertin commented Sep 19, 2018

I have problems with:
session_regenerate_id(true);
https://gist.github.com/eddmann/10262795#file-securesessionhandler-php-L74

I lose the information of the current session and the files of the previous sessions are not deleted from my temporary directory.

Copy link

ghost commented May 5, 2019

Do not use mcrypt_* or openssl_*. Mcrypt is insecure, and OpenSSL is hard to get right, only cryptography experts should use it.

Everyone should be using Libsodium.

DO NOT USE THIS CODE. IT IS INSECURE.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment