How are PHP session id cookie encrypted? - php

I just want to know how PHP encrypts the session cookies.
The reason is for example, if 24 always get encrypted to _randomString, then an attacker can make a request using that _randomString as the session ID, thus impersonating the user with id=24.
Even if 24 doesn't always get encrypted to the same _randomString, what I am worried about is the fact that PHP always encrypt in a certain way and we can't change the secret key for example, Which makes it easy for an attacker.
Also I am not sure if PHP use A secret key encryption.
Thank you

Related

Storing the user Password (serverside), connecting it to a cookie - security Issues

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)

Passing URL parameters with PHP

I am creating a program that communicates with a PHP script on a web server and to do so I need to be able to pass parameters from the program to the PHP script.
Now here is my question. At some point the user name and password needs to be passed to the script. Now this is not done in a way that is apparent to users (such as in an address bar) but I know with a little sniffing around someone that really wanted to could figure it out. So while my script is safe from injection, obviously variable tampering is an issue here.
This is an idea I have come up with so please help me wrap my head around it and see if this would work the way I THINK it will.
My thought was to encrypt the user password (or another unique key) variables on the client side before sending so you get a url like (obviously just made up) mypage.php?un=Oa348uty8&ps=op986hGTfreu Then when it gets to the PHP script decrypt it and encrypt it again with a different salt.
So when it leaves the application it would be encrypted but not the correct way, and then when it hits the PHP script server side decrypt it and re-encrypt it with the correct salt so it would correctly match the stored encrypted password.
This way, they user would not know what the encrypted version of their password is supposed to look like so without that they would not be able to tamper with the URL and try to insert fake values.
To put it in a nutshell, you are thinking of this:
On server side you have:
a database, with login/password matches.
a script that take 2 parameters (password and username) and check in the database if the couple exists
Your problem:
When your local application call the php script on server side, the 2 parameters are given in plain text. And you want to avoid tampering ( if your script are safe against injection i only see tampering used to bruteforce the auth <= keep in mind that i will keep this assumption in the whole post)
Your solution:
On client side, encrypt the 2 parameters
On server side, add a salt in your script to salt
Then decrypt the 2 parameters and encrypt with a salt
What I think:
This will not solve the tampering issue, someone can still forge requests.
The first encryption is useless because someone can retreive the key used by your client.
The second encryption is not safe enought because you use the same salt for all you users.
What I suggest:
Accept that tampering can't be avoided if you don't use a secure protocol like HTTPS (can either use SSL or TLS).
If you want an acceptable security without HTTPS the following is what i would implement:
A token system that you will check in order to see if the user can perform the login operation
A username that would not be encrypted
The password sha1 hashed stored in database
On client side, you call the script and provide the username as non encrypted and your password as a sha1 hash, rehashed with a random salt (sha1(sha1(pass)+salt) (the salt is stored in the user session on server side)
The script would then compared the provided hash with db password hash rehashed with session salt
The improvement is that the attacker must try to brute force two sha1 passwords consecutivaly and must provide a valid token to perform the login action. Plus if you use as salt a string using hex char of a variable even length, it will make the job harder for the attacker to recognised that the value bruteforced by the second hash is a sha1 hash, and even if he know it's an sha1 he will have to test multiple case to try to find the right portion of the value that correspond to the hash.
Because of variable salt, a same password won't be the same if hashed:
Imagine the attacker sniffed a hash and know which password was used then sniff another hash that was made with the same password as the other, the attacker won't be able to know that the 2 password where the same( a little overkill but still usefull).
It is safer to store the password as hashed value, because if the attacker manage to dump your user table, he won't be able to use the passwords right away, he would have to bruteforce each of then.
Finally sha1 hash are safer than md5 (i tell you that because you used the md5 tag in your post)
The downside of this method is that passwords can't be reversed, so you won't be able to given them back to your users if they lost it. You will have to make them set a new one.
An hardcore way (still without using HTTPS), would be to encrypt your password and username with a strong cypher (like AES or 3DES) and use a secure key echange algorythm (like the Diffie Hellman one) to exchange a random shared key.
This method won't block tampering, but will screw the attacker, because he won't be able to decrypt the value (assuming he only is sniffing the network). The key is random and never hardcoded in any of your application, so even if someone reverse your client, he won't be able to retreive a key.
I would still recommend to store your password value has hash.
An extreme way would be to merge the 2 methods but would be completly overkill.
Hope this will give you ideas
The problem with your approach isn't whether you are using encrpyted passwords and usernames in the URL or not. If the user authenticates by sending the encrpyted strings to you, then I as an attacker can still sniff out those hashes, pass them to your application and authenticate. This is unless then, that you do some public key/private key exchange before hand, but that is just reimplementing HTTPS, so you might as well just use HTTPS.
What you should do is to send the request using POST over HTTPS.
POST: So that the authentication details will not be in the URL and show up in logs and referrer URLs.
HTTPS so that the content of the whole request is fully encrypted and can only be decrypted by the client application and the server side.
encryption with Javascript from client to server only prevent from non SSL posting fails.
I think you must use sessions instead of this type encryption .
Update:
You could add your own secret key in both scripts.

phpsessid - Is it worth changing the session name to something hashed and visitor specific

I'm wondering whether for security purposes it would be worth using the session_name() function to rename the default phpsessid to a hashed or encrypted id?
If so, what would be the best way to implement it??
Thanks,
There's a lot written about this on the web, and previous questions I've read on StackExchange. Encrypting your session_id just creates another random number that is as easy to hijack as the original random number.
If you think about it, if you encrypt a session you will either reassign session_id to the new number (in which case you have achieved nothing) or you will use encryption / decryption functions in your script.
If you use the latter method, and someone get's hold of another users encrypted Session ID, it will be decrypted by your script and access will still be granted.
In short, there is very little point and no real utility in further encrypting your session_id above and beyond the random number it is assigned.
Rename PHPSESSID to another name, say MYNEWNAME, because anybody with little idea about PHP knows that HTTP server doesn’t maintain state and can only keep track of users using PHPSESSID.
The PHPSESSID is stored in the clients cookie so I don't consider it as secure. Someone might bruteforce it and perform some action (like a Facebook status post) whenever a session was successfully hijacked. Read more on https://codereview.stackexchange.com/questions/75310/protect-from-people-bruteforcing-the-phpsessid

Is it safe to keep the user password hash on session ? PHP

Is it safe to keep the user password hash for example md5 in session ?
UPDATE: i wanna use this hash for farther authorization of ajax requests that asks the user password, I got a key too but i have to check the password too.
It should be safe, since a client can only access his own session values. But you should:
make sure the client cannot access it
use another encryption, I wouldn't consider md5 safe, better use SHA-512 or something else.
But most importantly: Do you really need the hash in your session? If the user has been authenticated, he will always receive the same session (if your server is configured correctly). If you are anxious about session hijacking, you are going down the wrong path.
There is one thing that you have to keep in mind is that session are usually stored on the hardriver on which your server runs. If someone can gain unauthorized access to any file on your server, those hashes can be compromise.
Wheter this risk is acceptable, depends on what you are developping.

What's the best method to protect login cookie data in PHP?

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.)

Categories