123
-=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- (c) WidthPadding Industries 1987 0|699|0 -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=- -=+=-
Socoder -> Web Development -> secure login system

Mon, 20 Jul 2009, 08:01
JL235
I am building something new on my site and for this I am planning to use PHP Sessions. I've never built a login system before so I want to do this right, with my main worry being that users may be able to alter their cookies to look like other users.

Is the following a good system, and if not why?

Every user has a unique userID that states who they are. When they successfully login a unique, randomly generated value is created and used as their sessionID. Both userID and sessionID are stored in the PHP session and server side in a database table called SESSIONS. On every page they visit I retrieve the userID and sessionID from the current session, and check if the SESSIONS table holds a row that matches. No match, no entry.

So in theory if they change their userID to a different users userID then their session no longer validates because their is no matching pair of sessionID/userID in the database.

The userID/sessionID pairing will also be timestamped in the SESSIONS table to allow them to expire on the server side.

Thoughts?
Mon, 20 Jul 2009, 10:02
shroom_monk
If I remember correctly, the session ID is stored automatically as a cookie on the client computer when you use sessions in PHP. You can then use session_start() to activate sessions, and check for any session variables stored on the server relating to that session ID. Thus, the only way for someone to pretend to be someone else would be for them to steal the cookie from the other computer, and use it themselves. But with cookie expiry, this isn't really an issue.

-=-=-
A mushroom a day keeps the doctor away...

Keep It Simple, Shroom!
Mon, 20 Jul 2009, 11:27
HoboBen
I'd also tie the SessionId to the user's IP address, to prevent people stealing sessions. (i.e. when they login, hash their IP address in with the SessionId that you give to them.)

But what you described seems to be a fairly common method.

-=-=-
blog | work | code | more code
Mon, 20 Jul 2009, 12:09
JL235
I don't quite understand/agree about hashing the IP because if your in contact with the victim (i.e. messenger) it's straight forward to get their IP address and so the perpetrator can just hash the victims IP themselves to get the hashed version.
Mon, 20 Jul 2009, 12:28
HoboBen
It would be a part of the SessionId, not something you could change yourself.

E.g., if you generate your SessionId like so: (pseudo-code)

sessionId = Hash(userId + "" + RandomId + "" + userIp)

The resulting hashed sessionId contains the IP address, but as it's part of the hash, it's locked to the the user's session and visiting from somewhere else will need a new sessionId.

-=-=-
blog | work | code | more code
Mon, 20 Jul 2009, 19:35
JL235
I'd really like to see Jay's thoughts on this. For example how does SoCoder do it?
Tue, 21 Jul 2009, 02:37
Jayenkai
A long long while ago, me and Stealth had a big to-and-fro about this.

If you want to log in at multiple places, on multiple devices and things like that, you don't want it to be "Per-login", otherwise you'd have to log in each time.
You could probably hold 100*devices and logins for every single user, but if you end up with 100,000 users, that's a lot of data.

You also want the user to have the ability to log-off, without it then buggering up your system and wiping off every other instance of their login.

And even then, for every complex solution we could come up with, the answer was very very simple.
"If someone gets it, you're screwed"

Even if you come up with a 1 million character super-encryption code, that could never ever possibly be cracked..
"If someone gets it, you're screwed"


Socoder works on the tried and true "Username + Hashed Password" method.
I spend less time worrying about that, and MUCH more time worrying about people hacking into the site.
Remember when we were on about the Java/Flash, and I said "But they can get your cookie!!", and got really really worried about that?

Worry less about what your cookie contains, and worry more about the fact that someone's hacking your machine.

-=-=-
''Load, Next List!''
Tue, 21 Jul 2009, 07:01
oscar
There are things you can do to make it more secure, like never storing a plain text value, and if possible (especially for things like logins) concatenate a couple of fields together to make it that little bit harder to guess.

And just perform a check against the values in the database each time a sensitive page is loaded


Guessing md5($username.$password) is a lot harder then guessing md5($userID)


@jay: theres also the potential for your headers to give stuff away in flash. If you're using a post or get to a page, someone can experiment by sending different values to teh script and seeing what comes out (a remote chance but still a possibility).

Tue, 21 Jul 2009, 07:20
Jayenkai
Oh yeah, and another issue with IP's.. A lot of folk still don't have static IPs, and they'll keep being continously logged out of the website.
Don't do that, if you want to keep folk logged in.. It's really annoying!

Additionally, Sessions end when you close the browser.

-=-=-
''Load, Next List!''
Tue, 21 Jul 2009, 09:49
CodersRule
I use a very insecure method when I create login systems...

I should make it use sessions, but I don't.
It's also EXTREMELY slow. So don't tease me about that part.

When I log in, I store their username and their password hash in a cookie.
Then, on EVERY SINGLE page, I check the cookie and make sure it's the correct username+password combo. If it's not, I send them to the bad login page. I know it's slow. If I used sessions, I would only have to check it once every log in... Then I clear the cookie when you log out.
Tue, 21 Jul 2009, 11:17
HoboBen
@CodersRule,

I don't see why that would be slow. I've used the same method, with ridiculously long hashes (sha512 or whirlpool), as well as another hash for session validation. The time spent checking that is almost unmeasurable.

Whichever method you use, you've either got to check username+password or the session on every page... I don't think there would be much difference in the time taken.

So I'd assume there would be some other problem causing the slow-down.

----

I don't see why it's insecure, either.

I don't like the idea of sessionIds because if someone has read-access to your database (fairly common on shared hosts), they can log-in with this data.

If you store a hashed password in a cookie, and a doubly-hashed password in the database, someone reading your database updates won't be able to log in.

I like to combine both methods, but I make sure that I use a really good hashing algo, such as sha256, sha512 or whirlpool.

-=-=-
blog | work | code | more code
Tue, 21 Jul 2009, 21:51
CodersRule
I said it's slow, because if you compare it to the other methods people use, this one actually has to read from the user's computer on EVERY page load. I figured it would be insecure because it's not complex. (although I do check for mySQL injections)

I just knew there were gurus on the forum, and knowing me, I would probably get criticized for using something so simple
Wed, 22 Jul 2009, 05:19
JL235
After some more research I believe the session values (like username) are only stored server side. So there is no need to make and maintain my own session id.

I believe this is what Shroom was pointing at.