<?php
require_once('utils.inc.php');
require_once('../handlers/stackSess.inc.php'); // base class defn
require_once('../handlers/encrypting.inc.php'); // encryption layer stacked on...
require_once('../handlers/compat.inc.php'); // storage layer
session_name('PENCSID');
logger("started");
$storage=new compatSessionHandler();
$storage->setLogger('logger');
$enc=new encryptingSessionHandler($storage);
$enc->setLogger('logger');
logger("ready");
if (!$enc->install()) {
print "set handler failed";
exit;
}
logger("* about to call session_start()");
session_start();
if (!isset($_SESSION['c'])) {
$_SESSION['c']=0;
}
if ((integer)$_SESSION['c'] && !($_SESSION['c'] % 3)) {
logger("* about to regenerate");
session_regenerate_id();
if (version_compare(PHP_VERSION, '5.5.1') < 0) {
// we have to tell the encryptor to create a new key
$enc->createKey();
}
}
++$_SESSION['c'];
logger("about to finish");
session_write_close();
?>
<html>
<H1>The Encrypting Handler</H1>
<p>
This provides encryption of the session data making it safe to store sensitive information in backups
and on shared servers, albeit at the cost of some extra processing. View the source of this file for an example.
</p><p>
The handler generates a random encrpyption key which is sent to the client in a Cookie (using the same
parameters as have been configured for the session cookie). The default name for the cookie is 'x' + session_name(). This can be overridden in the constructor.
</p><p>
Note that the handler does not implement storage and needs to be stacked on top of something which does!
</p><p>
The session ID is used as an <a href="http://www.cryptofails.com/post/70059609995/crypto-noobs-1-initialization-vectors">Initialization Vector</a>.
<p></p>
The default encryption algorithm is AES-256.
</p><p>
<b>Important</b> Like the session ID, the encryption key is vulnerable to fixation, further, PHP prior to 5.5.1 does
not implement the hook for regenerating the session id, hence on any authentication transition (and preferably on presentation of a non-existent session ID)
your code should call session_regenerate_id() <em>and</em> the code necessary to create a new encryption key:<br />
<code><pre>
session_regenerate_id();
if (version_compare(PHP_VERSION, '5.5.1') < 0) {
$encryptingSessionHandler->createKey();
}
</pre></code>
<br />The code will emit a warning if the session ID changes but the encryption key stays the same.
</p><p>
While Suhosin also has the capability to encrypt session data, the <a href="https://www.idontplaydarts.com/2011/11/decrypting-suhosin-sessions-and-cookies/">key generation</a> (using one or more of a fixed string,
the user agent, part of the client IP address and the path to the document root) can, in many cases, be determined
from other artefacts on the system. Also both the User agent and IP address can change mid session leading to a loss of session data. On the other hand
the native code implementation of Suhosin means that it will probably scale better.
</p><p>
There are a lot of other encrypting session handlers out there however
<ul>
<li>Most fail to expose the key regeneration method allowing fixation attacks</li>
<li>Several undermine the encrpytion by doing silly things like hashing the key before use (reduces entropy)</li>
<li>You need to do a lot of coding to change the underlying storage mechanism</li>
</ul>
The handler itself uses a slaved object (class included in file) to deal with the actual encryption. Hence you can change
the encryption algorithm easily, for example substituting the null encryption engine for debugging.
</p><p>
You can expect this to add a significant CPU cost to each request.
</p><p>
Here is the output logging generated by this script:<br />
<?php
print "OK:++\$_SESSION['c']=" . $_SESSION['c'] . "<pre>$statuslog</pre>";
print "<hr />session = <pre>" . var_export($_SESSION, true) . "</pre>\n<hr />cookies = <pre>" . var_export($_COOKIE, true) . "</pre>";
exit;
|