How can I encrypt, and later decrypt, a cookie value in PHP? How secure will the encryption be?
There a variety of different ways to encrypt information in cookies and elsewhere. The strength of the encryption will vary by the method you choose to do the actual encryption. mycrypt is a good place to start. See this answer for an example of using mcrypt.
I don't recommend putting anything sensitive in a cookie, even if it is going to be encrypted. Way too tempting for someone to crack. Try sticking to sessions if you can.
I am in full agreement with the other answers: If the data is truly sensitive it should be stored server side in a session, not in a cookie.
As far as ways to encrypt cookie contents, the Suhosin PHP extension provides the ability to transparently encrypt all cookies. If you have the ability to install PHp extensions this may or may not be easier for you than writing your own encryption scheme.
If the cookie is encrypted securely (for example, with a server-stored secret that changes on a regular basis) I see no problem with storing useful data in the cookie. Why store it on the server? Make the client do some work for a change -- especially if it is preferences. Why should the server have to constantly store and retrieve data from a session file? What if you have hundreds of thousands of users pounding your site? Now you have to maintain hundreds of thousands of session files.
I can think of a reasonable use for this. Suppose you have a large server farm, you're going to have a bottleneck at the database and/or memcached server for handling session requests.. "is this user logged in?"
If you were to store the users session data as an encrypted value in the cookie, then you can prevent having to do quite a few read/writes and allow for an unlimited sized cookie store since there is 0 impact on your side other than being CPU bound for encryption/decryption of the cookie data.
Ruby on Rails by default does this - although it only signs the data and does not encrypt it. There is an alternative implementation which encrypts the data with its own key and signature so you the user is not able to see what data you store in their session.
I can not simply think of a situation where encrypting data in the cookie is useful. If you want to retain secret data about the user or his preferences, information, whatever, then store it on the server in files, in the session or in the database, but not in the client's computer.
On the other hand, if you creating an authentication, then you should use sessions instead of creating secret encrypted cookie values. Sessions weren't implemented for nothing, they are the way to go.
Related
I would like to know if it is a good idea to sign cookies with hash to check it's integrity? First of all, I do realize that I should not store any sensitve data in cookies and use sessions instead. That's exactly what i do. But still I am feeling not comfortable with user being able to modify even not so important data. (I'm kind of security paranoic :) )
I came up with the following solution. Let's say we have cookies for:
PHPSESSID
site_lang
recently_viewed
Now whenever I update cookie value I recalculate hash for cookie with key of let's say cookie_hash and value of let's say md5(serialize($_COOKIE)+$secret)
the only thing that I am not using PHPSESSID for calculation and validating hash because it is not being managed by CookieManager class (my custom class) and might be refreshed with new session id and corrupt hash.
My concern is what if some third-party package sets it's own cookie bypassing my CookieManager of course. it will collapse hash. So is it a good idea at all?
MD5 is weak for this, and the scheme you proposed (hash(data||secret)) is flawed anyway. Cryptography is hard, please don't try to come up with your own. :)
What you may be looking for is invented already, it's called message authentication. Have a look at things like HMAC, which is one proper way to do something very similar.
In most cases, authenticating cookie values doesn't make sense in a web application and provides no additional security, but there are cases, when it does. Your examples above don't seem so. :) For example the session id is cryptographically random already, and the other two usually present no harm if changed by a user (but in very special cases, they probably may, though I can't come up with a reasonable example). If something matters and should not be changed by the client (user), that should probably be stored in a server-side session.
However, you may decide to store application state on the client in encrypted and/or authenticated cookies, one reason for that may be a stateless application on the server (see the default session management in Ruby on Rails for example), and in that case, something like your idea (but done correctly) is indeed the solution, but it has its own set of risks (as do server-side sessions).
Note that anytime you store state on the client, one threat that comes up besides secrecy and authenticity is replay. This affects your idea as well. Say it is a problem in your application if the user can change the last_viewed cookie, but you still don't want to put it in the session. You properly authenticate the cookie, maybe even encrypt it, the client has no access. But what if at some point, the user saves the cookie, and in a different session replays it? (Okay, your example tries to protect all cookies at once, which may make this a little bit more difficult, but you get the idea, replay is still a potential problem.)
So in short, you most probably don't need this, but if you do, then use proper message authentication (something like an authenticated encryption, or a proper MAC like HMAC).
I don't know how deep you digged in PHP and Webdevelopment, so please forgive me if the level of my answear is to low.
If you are paranoid you should read more about PHP, sessions, cookies, hashing algorithms and more.
For example:
PHP session handling
PHP session configuration
PHP session security
With this you can modify your sessions & your handling a little bit to serve your paranoia.
By the way you shouldn't use something like md5 in reference to make your web application more secure.
If i understand what you want to do, you want to write a hash of your serialized session array plus a secret/salt into the session to verify the integrity of the session and its data.
If this is your motivation, you really should rethink, at least in my opinion.
A session is just a file on your server (on the users system it's a database entry in a sqlite database of firefox or something else, but without the data you write to the cookie array, that data are just writen to the server) and the session ID is a file name/path to this data on the server, except your sessions are saved on a database.
So with your approach you would just save the value to verify the integrity of the data in the same data (on the server) you want to verify.
And where you want to save the secret?
I think it's a little bit useless.
Depending on your needs and the needs of your application you could search about the key word session TAN, you could set a additional cookie with a random value you save on the session to verify each other, you could save and check the IP (depending on the law of your country and the way your users connect), shorten the session lifetime and more.
You could also set ini directives like session.cookie_httponly (that's one i recommend if you don't want to access your session cookie by a script language like JavaScript) you can find on the links above and more.
Something is a matter of faith, something evident.
Digg in deeper and understand how the technology works under the hood and you can make your decision more easy by yourself.
Lately I have stumbled upon some articles that suggest using a cookie to store session data.
I liked the idea and extended my session storage by adding a CookieStorage class which works fine (note that per user I use a unique hash key for sigining and encrypting data)
However, there are a lot of other articles that suggest against storing sensitive data in a cookie, even though you encrypt and sign the value.
Personally, I find no reason why not do it especially when encrypting and signing the value with a different key for each user. The risk of the data being compromised is the same as with normal sessions, no? Not to mention that if you use SSL then the risk for hijacking is eleiminated.
What I see as a benefit with such an approach, if the session data are not large, is fewer IO operations on the server for opening/reading/writing session data, whether the storage is file, db, memory based
I would appreciate your feedback on the matter
Thanks
If you're using pure cookie storage with no server-side component at all, then the user is in control of the data. The only thing keeping him from it is your encryption/signing method; but that can be attacked. If you're not using encryption/signing keys specific to the user's session (i.e. you're not using a server-side session), then you're pretty much limited to a static secret. Someone could attack that offline, trying to brute force it. Once they did, they could spoof their entire session.
If you are using more secure one-time random secrets stored in a server-side session... you're already storing data in a server-side session! Why not keep it simple and store everything there? It would also reduce the bandwidth needs required to transfer all the cookies back and forth with every single request.
If you're doing this mainly to save I/O operations on the server: use a more efficient session store like a memcache based store.
Although nowadays session id transferred only via cookies, initially there was other ways, which are still supported and can be used.
Sometimes server needs to know or alter the session info.
That point from #CBroe on the cookie size.
I'm coding a private message system in PHP for secure encrypted communications.
Every time a user registers an account, I'll create a new RSA private key using phpseclib and will encrypt it in AES using the user's password, which will be securely stored hashed and salted in the database.
Every time a user logs in with his password, he should also unlock his private key and maintain it on the fly.
This script is obviously intended to run only under SSL connections.
The problem is that I need to maintain a non-encrypted version of the private key in the user's session to make sure he is able to read every message and write new messages without inserting the password on every page refresh.
Storing in the PHP Session is not a secure solution since the PHP Sessions are still stored on the server and can be compromised.
Storing it in a Cookie is not a good solution since a Cookie can be easily stolen (but in this way I put the destiny of the user in his own hands).
Is it possibile with ajax to maintain the key in a PHP variable (not Session) and never refresh the page but getting and writing messages using ajax? or is there a better solution?
Thanks in advance.
Assuming you have full control and can limit access/visibility to your database, you can switch over storing your session data from file storage to using database as session store. This assumes of course your db is secure enough for your needs. You can check out a detailed overview on how to setup php for storing session to your database here: http://www.stanford.edu/dept/its/communications/webservices/wiki/index.php/How_to_use_MySQL-based_sessions
Assuming you don't need to preserve session data across a database restart, you could also make the session store table's storage engine to be MEMORY instead of Innodb or MyISAM. This will make it pretty snappy and avoid the concern you might have of session data being inside the db files on disk in an unencrypted state.
If you store the private key anywhere on the server, then it's only as safe as your trust in anyone who has root access to that server. For a secure messaging system, not all your users may want to trust the people who can access root. (Do they?) That suggests you'd want to store the private key on the user's machine. As you suggested, doing that is a whole different set of security questions.
I'm assuming your users are using web browsers to access your system, since you mentioned cookies. Most web browsers also support the idea of local storage (non-cookie), which might be an option to investigate; I'm not expert at all in that area so won't comment further.
Security is hard, and complex. Be wary of any simple answers, and be aware that no security is perfect. Good luck.
I'm creating a login system in PHP, and I want to know how to best protect the user information string in my cookie. I was thinking of encrypting the string with a key somehow? Is this the best way? I'm kinda new to this.
Thanks in advance.
Don't store sensitive information in cookies. Store a session ID hash to connect the logged in user with their account.
Aaron Harun has the right answer for you. There's basically no need to encrypt such data as long as you store it in a session, because that data never reaches the client/browser/user, as it is all server-side. When you create a session on PHP, it handles the cookie stuff for you, so you don't have to worry about that. In most cases, there is no need to deal with cookies. In security, dealing with cookies is detrimental.
I've seen some sloppy sites that actually store the username in a hidden field on a form, which allows anybody to simply edit their local copy of that form and take actions as whichever user they like. This seems like an obvious problem, but cookies are no better.
If you truly think it's a good idea to design a homebrew authentication system, you need to design the database first. Don't store plaintext passwords, store a hash instead (like md5, sha-1, etc) and at that point there's no harm in generating a salt for each password (a random string that you append to the user's password before hashing it, and store that salt with the password hash because you'll need it later--this prevents dictionary hash attacks, ie rainbow tables).
You should never store secure information in a cookie. Cookies are saved in textformat on the user computer, and there are many reason why you should never stock sensitive informations in them :
Cookies are basically text files, which can be opened by anyone on the computer, with any text editor.
The cookies are stored on the user computer, this mean he have no time limit, no connection limit, no processing limit, so he can try to brute force any data as much as he want without being worried of getting ip banned/kicked...
You should only stock things like a username to remember or a session id.
If you absolutely MUST store information in a cookie instead of the user's session, consider signing it with HMAC. The hash_hmac function is a builtin in modern PHP versions.
If you're storing a user login for a "remember me" feature, store both the user's ID and a hash of information that is only available in your database. For example, hashing together the login name and password and storing that with the user's ID in the cookie is reasonably secure. If the user ever changes their password, all the machines he's logged in to with that method would be invalidated, and there's no way to simply change the ID in the cookie and still get logged in, because the username/password hash won't match.
You get sessions for free! That is data stored server side, automatically handled by PHP/framework-of-your-choice. You just put data into the session, which is associated with a random UID stored in clients' sessions. On the clients' side, this is the session cookie. This ID is automatically generated, you can fine grain the behavior manually.
Data stored client side is never safe, no real encryption available. Sessions you will need anyhow for keep track of logged in users. If you have lots of data, you can use the ID to identify associated data from other datastores (DB, XML etc.)
I'm bit confused. I've been building my sites with my own session system, but i'm not sure how secure the php's own session system is. My session system usually just has user id and quite harsh hash, which does not include user name or password for generation. I save the hash in the user database and as a cookie to confirm the user session on every page load. So my question is can i trust php sessions or keep using my own?
PHP saves a unique session id in a cookie, and all values related to the session in it's own text file on the server. You have to get the session id to steal the session, which means you have to steal the session cookie from the victim's computer. PHP's own system is at least as safe as your homebuilt system
The difference may be how hard it is to find an active session by brute force. That is entirely up to the hashing algorithm and the random number generator.
You can configure PHP to use different hashing algorithms or you could even use your own algorithm to create the session ids for PHP's session system if you don't trust PHP to do it properly.
Storing data in cookies versus using PHP's sessions is very different. Cookies store data on the client-side; sessions store data server-side, which has a number of benefits:
The user can't see it
The user can't modify it
The browser doesn't need to send the data to the server with every request
Normally PHP sessions do store the session key as a cookie (although they don't have to), but none of the data you actually care about is ever sent to the user, it's stored on the server and looked up using the session key
i'm not sure how secure the php's own session system is
And the rest of the world is not sure how secure your's is. A lot of people have looked at the session handler in PHP and not found any flaws in implementation. Its also well characterizied and integrated but supports the notion of user defined handlers.
I'd recommend using the standard session code - but you might want to write your own handler functions.
C.