[web] PHP, sessions and security

Started by
23 comments, last by deadimp 16 years, 10 months ago
Since I'm commonly setting up web sites with a CubeCart installation for e-commerce (not all the time, but CubeCart gets the job done for 85% of anything you need to sell) I've incorporated the same session administration feature into the web site and the content management / backend of the web site as well - so if the need arises, logged in users to the web site will not have to re-register at the store section.

They handle it the same way as you, however they regenerate the session id at login.You also want to look into using mysql_real_escape to prevent sql injection attacks.

There's a lot more you can do to 'be on the safe side'. Give your sessions a timeout variable and update it each time they hit the next page and the timeout hasn't occured.

http://phpsec.org/projects/guide/4.html

http://www.devshed.com/c/a/PHP/Creating-a-Secure-PHP-Login-Script/
Mark A. Drake
OnSlaught Games
Mark Drake
Advertisement
Oh, use the md5 or sha1 function on the password before storing it in the database, then compare passwords by applying the function before the sql syntax. It computes the given password to a hash value. The point? You're database is leaked and they get a large list of hashes and usernames instead of usernames and passwords. It'll provide you the time to go through and change all the passwords quickly so that your customer's information is not leaked.
Mark A. Drake
OnSlaught Games
Mark Drake
Yeah, I've been storing SHA-1 hashes in my database, and I'm sure to escape strings properly before putting them anywhere near the DB.

I might do the session timeout, but I think that might be a bit annoying for some users. My forums don't need to be ultra-secure and I think it's unlikely that anyone will try session hijacking.
Quote:Oh, use the md5 or sha1 function on the password before storing it in the database


I recommend something tougher. MD5 hashes for (short) passwords are easily recoverable with the help of rainbow tables. Take a look at the hash functions to see what's available. MD5's good enough for e.g. a blog or a forum which are not interesting for a hacker to steal and run through rainbow tables, but you should push for the best when dealing with e-commerce or other sensitive (private) data.

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

One thing about storing session ID's in the URI: What happens when a malicious user links to the site, and gets the ID using the referrer? Though, it'd be unlikely someone would go through the trouble to do this, and unlikely that they'd be monitoring the data gathered from potential victims.

I'm currently designing a CMS, Thacmus, and the user security is very basic - essentially what markadrake and others have stated: I just store the username and password (hashed with md5) in the session. However, looking at Sander's suggestion, I might change that some.
I can't say the security's really been tested in the real world, I've only released it recently, and there's been only a couple or so unique visitors to the website running the CMS.

I might be designing a forum using Thacmus later, but I don't think I'd worry about users with cookies disabled. Not every user base can be covered.
Projects:> Thacmus - CMS (PHP 5, MySQL)Paused:> dgi> MegaMan X Crossfire
Quote:I just store the username and password (hashed with md5) in the session.


Listen to benryves and also store the user's IP address and user-agent string in the session table. When you get a session ID simply check that the first 3 parts of the IP address(*) and the user-agent string are still the same as what you stored in your session table. If not, silently destroy the session and create a new one.

(*) Matching only the first 3 parts, e.g. 192.169.1.* ensures that people using a broken ISP that reroutes traffic through different proxies on each request (e.g. AOL, some dial-in ISP's) can still match their sessions.

<hr />
Sander Marechal<small>[Lone Wolves][Hearts for GNOME][E-mail][Forum FAQ]</small>

I noticed everyone's replies hit all of my points except session regeneration at login.

Sander - thanks for the link. But it doesn't necessarily say which is strongest of the available types. It's also 3 am and I'm feeling the inevitable keyboard / face-smack that will occur soon.
Mark A. Drake
OnSlaught Games
Mark Drake
Ok, here is how you do a secure login without HTTPS:

0. Use session_set_save_handler() to implement secure session storage (maybe in a database) or session_save_path() to use another directory than /tmp.
1. In the login form, have a hidden field with some random value set by the server.
2. The client will use hex_md5(key) on the password and then hex_hmac_md5(hiddenkey, crypted_password) on the result and send it to the server.
3. The server uses the same algorithm to validate against the database of login users.
4. (Assuming validated) Set $_SESSION['login_user'] to the value of the logged in user and don't care anymore. Use session_regenerate_id() to invalidate the session id.
5. ...
5. Profit! =)
Quote:Original post by Sander
Quote:Oh, use the md5 or sha1 function on the password before storing it in the database


I recommend something tougher. MD5 hashes for (short) passwords are easily recoverable with the help of rainbow tables. Take a look at the hash functions to see what's available. MD5's good enough for e.g. a blog or a forum which are not interesting for a hacker to steal and run through rainbow tables, but you should push for the best when dealing with e-commerce or other sensitive (private) data.


Unsalted md5 can be recovered quickly through rainbowtables, usually within a few minutes. (maybe hours)

However, store a salt value, and use it.

ie. caluclate sha1(salt ^ md5(password)) with a 128 bit salt. You store the salt as an additional field.

This is surprisingly secure against attack. (brute force/dictionary attacks are the ony things that can put a dent in, however any precomputed attack (time/memory tradeoffs like rainbowtables, ktables, etc.) are foiled.)

Also, you could create a derived key from the password and username (ie. sha1(md5(username) ^ md5(password)))), and encrypt your sensitive data with that when needed. (if you have anything that sensitive).
Click here to patch the mozilla IDN exploit, or click Here then type in Network.enableidn and set its value to false. Restart the browser for the patches to work.
Im just beginning with PHP so this topic is pretty interesting to me. Forgive me if this is naive, but what is wrong with the following security model:


1) On the login page, gather their username and password.
2) Compare these with the USERPASS table in the database.
3) If the login is valid, generate a Big Random String (BRS) and store it in the SESSION table in the database. Also return the BRS to the login page.
4) For every secure page on your site, check that the BRS (passed on GET or POST) is in the SESSION table. If it is, you know its a valid user.
5) When the user logs out, or times out or whatever, remove the BRS from the SESSION table.

This doesnt use Cookies, or the Session PHP utility, but It does of course use mySQL.

Comments?

This topic is closed to new replies.

Advertisement