Tag Archives: Security

Encrypted session handler

[UPDATE]  Enrico Zimuel has a better version of this[/UPDATE]

A little while ago I had come upon the problem of having to store sensitive data in a user session.  The solution that I (and several others came upon) was creating a mechanism for storing encrypted data in a session.  But what we wanted to do was build something that didn’t have a single point of failure.  We also wanted to build something portable.  What we built was a simple Zend Framework session handler for storing sensitive data.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class EncryptedSession extends Zend_Session_Namespace {
 
    const CIPHER = MCRYPT_3DES;
    const MODE = MCRYPT_MODE_CBC;
 
    private $_iv;
 
    public function __construct($namespace = 'Default', $singleInstance = false)
    {
        parent::__construct($namespace, $singleInstance); // Must be true because of iv
 
        $storeKey = __CLASS__ . '_Data' . '_' . $namespace;
 
        if (!isset($_COOKIE[$storeKey]) || !isset($this->secretKey)) {
                $this->unsetAll();
 
                $maxKeySize = mcrypt_get_key_size(self::CIPHER, self::MODE);
 
                $secretKey = '';
                while( strlen($secretKey)<$maxKeySize) {
                    $secretKey .= dechex(uniqid(mt_rand(), true);
                }
                $this->secretKey = substr($secretKey, 0, $maxKeySize);
 
                $iv_size = mcrypt_get_iv_size(self::CIPHER, self::MODE);
 
                $this->_iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
 
            $hmac = hash_hmac('md5', $this->_iv, $this->secretKey);
            $unique = base64_encode($this->_iv);
            // The cookie has the same parameters as the session cookie
            $cookie_param = session_get_cookie_params();
            setcookie(
                $storeKey,
                $hmac.$unique,
                $cookie_param['lifetime'],
                $cookie_param['path'],
                $cookie_param['domain'],
                   $cookie_param['secure'],
                   $cookie_param['httponly']
            );
        } else {
            $hmac = substr($_COOKIE[$storeKey],0,32);
            $unique = base64_decode(substr($_COOKIE[$storeKey],32));
            $check = hash_hmac('md5',$unique,$this->secretKey);
            if($hmac !== $check) {
                 throw new Zend_Session_Exception('Invalid Session Data');
            }
            $this->_iv = $unique;
 
        }
    }
 
    public function setEncrypted($key, $value)
    {
        $this->$key = bin2hex(
            mcrypt_encrypt(
                self::CIPHER,
                $this->secretKey,
                $value,
                self::MODE,
                $this->_iv
            )
        );
    }
 
    public function getEncrypted($key)
    {
        if (isset($this->$key)) {
            $decrypt = mcrypt_decrypt(
                self::CIPHER,
                $this->secretKey,
                pack(
                    'H*',
                    $this->$key
                ),
                self::MODE,
                $this->_iv
            );
            return rtrim($decrypt, "�"); // remove null characters off of the end
        }
        return null;
    }
}

 

 

What this does is allow you to transparently store encrypted data in a session.  Because it’s encrypted, someone hacking in to the server, say via an include vulnerability, would be able to read the session data, but not decrypt it.  That’s because the initialization vector is stored in a cookie on the browser.  So in order to decrypt the session an attacker would need to do both an XSS and a remote code injection attack.

Why you should be careful with phpinfo

27826_403171467139_190917412139_4129076_5062970_n

I recently posted an image on why you shouldn’t put phpinfo() calls in your code.

There were a couple of comments from people asking “why not?”

Here’s why not.

  1. Go to Google
  2. Search for inurl:phpinfo
  3. Check out the results

At the time of writing there were 4 pages on the first result page that were broadcasting their settings.

Here’s another fun one.  Search for “inurl:phpinfo root”.  Lots more.

There’s a bunch of information that you will see.

  1. PHP Version (which you can then check against for security vulnerabilites) – You’d be surprised how many PHP 4.3 installations there are out there.
  2. Which extensions are loaded (which may also have vulnerabilities)
  3. Where all of the website files are
  4. The username of the web server.  The second search will show up some scaring results.
  5. And much, much more!