-
-
Save eddmann/10262795 to your computer and use it in GitHub Desktop.
<?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 |
Hello,
I'm trying to use this library but am running into issues. The problem seems to be that it doesn't re-use any sessions. Everytime I refresh the page I get another file and no session variables carry over.
This doesn't work (no persistent sessions and files keep getting regened):
include('SecureSessionHandler.php');
$session = new SecureSessionHandler('DA2FC336BD9E3');
ini_set('session.use_cookies', 1);
ini_set('session.save_handler', 'files');
session_set_save_handler($session, true);
session_save_path(__DIR__ . '/sessions');
$session->start();
echo 'Secret 1: '.$session->get('secret1').'<p>';
$session->put('secret1', 'ExtraSecret');
echo 'Secret 2: '.$session->get('secret1');
This works fine (single file and persistent sessions, although no encryption):
ini_set('session.save_handler', 'files');
session_save_path(__DIR__ . '/sessions');
session_start();
echo 'Secret 1: '.$_SESSION['secret2'].'<p>';
$_SESSION['secret2'] = 'SuperSecret';
echo 'Secret 2: '.$_SESSION['secret2'];
SecureSessionHandler.php is your code above (up to line 162).
Prevent the session is started before using the method put or get:
public function get($name)
{
// prevent the session is started
if (session_id() === '') {$this->start();}
$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)
{
// prevent the session is started
if (session_id() === '') {$this->start();}
$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;
}
mcrypt_*
will be abondoned soon so that such functions should be completely replaced with openssl_*
.
Why isn't there a php-package for this?
Has anyone successfully used this class with PHP 7? Or could anyone point me in the direction of something else?
@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:
-
line 9, change $this->key = $key; with:
$this->key = substr(hash('sha256', $key), 0, 32); -
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); -
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
should be 'aes-256-ecb' or you get a warning about not using a IV.
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?
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
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
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.
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.
@jigglywhatsit
Yes, You can use both SecureSessionHandler.php and SecureSession.php together. Use SecureSessionHandler for starting/forgetting sessions and manipulating session vars. Then extend it to SecureSession to use as your session save handler.
First)
in SecureSessionHandler.php
Remove any methods that are already in SecureSession.php. You will extend the SecureSession class to use as your session save handler, so make sure that everything that SecureSession is doing is not done here in SecureSessionHandler.php.
mainly... remove all parameters(already set in parent SecureSession.php), constructor, setup, read, and write methods from SecureSessionHandler. There are some other small changes that need to be made to the methods in SecureSessionHandler. For instance SecureSession.php handles revoking the cookie so you can remove that from the forget method.
Second)
in SecureSession.php
remove the line"new SecureSession();" from the end of the file.
If you want to change session path you could add...
to the end of the constructor so that you don't have to do that manually after you construct your new object.
Third)
extend SecureSessionHandler to SecureSession like so.
class SecureSessionHandler extends SecureSession {
You could also replace the put and get methods in SecureSessionHandler if you like. They work well but I opted to use the magic methods __set __get __isset __unset so that I could more easily set/get session vars.
Usage would then look like...
or in a class...