Вопрос

I'm trying to find a secure Solution to a Problem I have concerning Cookies / Sessions and DB Data.

I already read trough different articles like http://www.devshed.com/c/a/PHP/Sessions-and-Cookies/ that explain different Cookie theft and Session fixation methods, to get an idea about the security issues I'm going to face.

The Problem is the following: I have DB tables that store data entrypted with AES_ENTRYPT(), using the user password to encrypt them. This means, to even read the Informations, I'll have to use the plaintext password to decrypt the data.

This probably wouldnt be a Problem, if I only store the password in the $_SESSION variable, but that would deny the ability to stay logged in over a cookie over multiple days.

In other words, I would have to store the plaintext password in the cookie (at least, to enable the feature to stay logged in)

Now, you could use a salted MD5() or SHA-256() hash as identifier, instead of the password. But I cant decrypt the data, with the hash. This means I would have to store the password server side (in a Database? Or are there other secure ways?), connecting it to the identifier - but then the password would be accesible for everyone that has access to the Database, and could directly decrypt the data there.

Is there a secure way, to connect an identifier that I store in a cookie, and connect it to a server-stored user input (the password / accountname) whitout actually giving someone that can access the Database the possibility to read that server-side stored user input?

The requirement is, that even in the worst case scenario, where someone has a dump of the Database and the cookie (but no access to the Server RAM) that person shouldnt be able to access the user password and decrypt the stored data with it.

To avoid confusion, a small recap:

This is not an user identification Issue - the login process happens separately (over the usual way: md5() hash of the password / logindata). My problem is, that userdata (like adress, name, email) is encrypted WITH the user password. So I need the password from the login, to decrypt them. This is no problem if the user just logs in, since I have the password in the $_POST data, and can use it. But after the log in? As soon as $_POST or $_SESSION is gone, I have no way to decrypt the data again.


Possible solution

After some input, I may figured out a way - it's not perfectly secure, but it should work well enough:

(This is separated from the login / user authentification process, I'm only refering to the encryption / key part)

user registers OR changes password:

    generate a new hash out of $email and $password => $auth

    do NOT store $auth in the usertable, just keep it

    generate a new random key for the user => $key (only on registering, not on pw change)

    encrypt $key with $auth, storing it into the usertable

    encrypt all user data with $key

user logs in (or after registering / password change):

    generate $auth ($password + $email)

    set cookie with $auth as variable

user is logged in (cookie / session / after login):

    decrypt $key with $auth

    use $key for data encryption / decryption (serverside)

The only Issue here is that if someone can get $auth, they could decrypt the $key and then the data. I'm thinking about generating a new $auth for every login, but this would raise the question how I decrypt the key if the old $auth is lost. The difference between this and a token is that this adds another layer, where the token isnt the encryption key itself. Anyway, I think the solution is the closest, outside of public / private keys, to what I intended. Thank you very much.

Это было полезно?

Решение

The key is to find a way to store a piece of information in the cookie and a piece of information in the database that together get the plaintext password, but individually are useless.

The best I can come up with is to create a random token similar to what @fire suggested:

$token = md5(uniqid(mt_rand(), true));`

Then use this token to encrypt the password and store the encrypted password in the cookie with the userid, so you know what this encrypted piece goes with.

When the client returns, the cookie can be used to retrieve the database row by id and you can pull the token from the database to decrypt the cookie information to get the plaintext password. This way if someone hacks the cookie, they get an encrypted password; if they get into the database, they get the key to unlock the password but don't have the encrypted password.

Другие советы

Have a field in your users table called token which can be a random hash when you first insert the user...

$token = md5(uniqid(mt_rand(), true));

Then store the user ID and token in the cookie, which you can use to lookup the user.

As I understand your requirement you cannot store the password client-side or server-side. Therefore you cannot store it at all. Make the user input the password for every page load.

You can store things in RAM using for example memcached or APC, or by creating your own software you can communicate with on the server. This will not give you much enhanced security as anybody who have access to the server (through a shell) can ask for the password in the exact same way as your software. In my opinion it destroys most of the purpose of the "no file, no database" requirement, but it may be a solution for you.

To keep the user logued

Use a simple token system, store the token in the user database AND on a cookie user-side. If you need more information about that, i'd suggest google (it's pretty simple)

For the plain-text password

You can use several methods to store it in RAM, this is an exemple with memcache

$memcache->set($token, $password); 

and then, retrieve the information from the RAM with:

$user_password = $memcache->get($_COOKIE['token']);

there is several solution to store data in ram with PHP: Memcache and APC (the user cache part)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top