After posting this a while back, I decided to create my own Registration / Authentication capability in PHP. I\'d love anyone to point out the flaws / opportunities for improve
Short answer: looks good!
Long answer:
To make sure you are handling your session security properly, check the guide on PHPSec.
My concern is could someone write to the session, and thus be able to access peoples pages if they know the username they signed up with? How would you go about preventing this?
I'm not sure what you mean. How would somebody "write to the session"? The session is [usually] a file stored on the server that the client cannot view or modify.
If you are concerned about session hijacking (aka fixation), then you need to enable SSL and disable session IDs in the URL string. (See php.ini's session.use_only_cookies)
4 - On every request, I use the username stored in the session to query the database and read the site name associated with this user. I then compare this to the site name in the url itself, and if they match I set a variable which is accessible to the rest or of the script (not a global variable, it's just readable by my controller which decides if a user can see a particular page) if the two site names don't match, the user is redirected back to login
This sounds like the biggest concern. What does the site name look like? How exactly are you matching it against the URL? With a regex?
Some more details on this aspect would be good, because if your access control is flawed then the quality of your authentication doesn't matter too much.
If I get the flow right, then if I know your username and site name, go to the site name and give you a cookie with the username (since sessions, after all, are saved as cookies), I'm in - no password needed? Isn't that a flaw?
Limit the velocity on logins. Log each attempt for a user and lock them out after so many failed attempts. As the failed attempts mount up, make the lock out longer and longer.
Add a salt in your code that is static and use it in combination with the salt from the database. Then if you db gets hacked, they still don't have the salt from the code. This salt can't / shouldn't change.
Can users retrieve passwords / reset lockouts? you will need to collect challenge questions and answers.
When users reset their passwords, do they have to know the original one?
If this a secure site, or just a site that tracks someone. I know of sites that you can take your cookie from machine to machine to login. It always remembers you, but is just a forum so the potential for trouble is low.
Why salt the code as well as the database? Once your database is hacked your site is toast. However seeing users tend to use the same password on many sites, no sense in helping hack everybody's property. If they get your code too then the royal screwing happens, but lets put up as many barriers as we can.
Security through obscurity is dumb, but many layers of security can help.
Regarding putting username in session Hash the username, url and a salt. Store that in the database and in the session. use that as authentication, if that isn't valid dump them to the login. they can't copy the cookie to another site, they won't be exposing their username as much, and it eliminates a query.
You can even regenerate that salted value every X pages views and store in the session to expire it and make stealing it less useful over time. You then would store two salts in your database. One for the password, one for the authentication session value.
Why 6 characters? Make it bigger and require a minimum of 6 (or more) characters. There is no excuse for limiting the number of characters in the password to 6.
Put more than the user name in the session. But to do this safely, you must change the salt every login:
A- From the login page: Take name and password verify with existing salt. If valid update the user table salt and password with a new salt (you have the password from the user so you can md5 it and the salt again). Write the md5 of the password to the session. B- From any other page: compare the user and hashed password against the database. If they don't match, redirect to the login page.
The flaw with this idea is the user cannot maintain logins on multiple machines/browsers.
Your registration system needs work to. How do you know the email address is valid? How do you know the user registering owns the email address? You must send email to the address containing a link back to your site which must be clicked before you allow the account access to anything. Otherwise someone can sign up under someone else's email address make fraudulent claims as that person or just cause your site to spam that person getting your site shut down.
You also might want to investigate CAPTCHA to limit scripted registrations.
If anyone is watching the registration form submission then they have the information you're concerned they'll figure out. First step: Use HTTPS for your forms.
As for the encrypted db stuff, I'll let someone else take issue with it. :-)