In general session information is not usually encrypted on the server side. It is generally assumed, as part of the threat model, that if an attacker gains access to the server then they already have everything they need. Session data itself is usually not any more sensitive than the rest of the contents of the database.
There are a few options:
- Store them on the filesystem in plaintext. If your threat model suggests SQLi is more likely than filesystem access, this is an easy move.
- Encrypt session IDs and data using the database's inbuilt encryption routines. This protects you against cases where a database backup is compromised, but won't protect you against disk theft or an attacker with SQL access.
- Encrypt your session IDs and session data in the database, using a key set in a config file on the server somewhere. The benefit of this is that the attacker would need access to both the database (e.g. via SQL injection) and the filesystem at the same time in order to decrypt the session IDs and session data.
- Encrypt session IDs and data using a randomly chosen key which is cached within the server daemon process (e.g. APC or memcached for PHP). This would be exceedingly difficult for an attacker to gain access to without full code execution on the system, but has the downside that all session data would be invalidated if you restart the server process.
I recommend the use of authenticated encryption, with separate encryption and authenticity. Pseudocode for encryption is as follows:
iv = secure_random(16)
encrypted = iv || AES-CBC-128(session_id || session_data, enc_key, iv)
auth_encrypted = HMAC-SHA256(encrypted, auth_key) || encrypted
Pseudocode for decryption is as follows:
mac = auth_encrypted[0:31]
encrypted = auth_encrypted[32:]
expected_mac = HMAS-SHA256(encrypted, auth_key)
if mac != encrypted_mac:
session was tampered with
iv = encrypted[0:15]
encrypted = encrypted[16:]
decrypted = AES-CBC-128_Decrypt(encrypted, enc_key, iv)
This provides authenticated encryption to prevent tampering with session data on the server side.