views:

63

answers:

3

I'm using php for my site and was wondeirng if it would be a good idea to use the $_SERVER md5($_SERVER['remote_addr'] + $_SERVER['http_user_agent'])) into a cookie_auth field in the user table.

When the user logs in, php will use the above key to re-check the current user and compare it to the stored key and if matched get credintials for the user.

The problems are, the user agent can change and IP can change. I guess my main concern is the user user agent. IP addresses typically stay around for a month or two and my primary user base has static ip addresses (companies) so this shouldn't be issue.

Are there any other php $_SERVER variablies that I could concatinate that would be less volitile... but still dynamic?

I have the php manual infront of me but I don't see any usefull... Maybe I'm missing something.

Do other developers implement anything similar to this?

Thoughts?

Is there a better way to go about this?

+2  A: 

It won't work, also because of proxies. If two people with the same user agent visit, then it's disaster.

Some projects can do "cookieless sessions" by passing the session id in a GET variable in all URLs that they use.

PHP can actually do this by itself. And you can even force PHP to not use cookies at all, just pass it in GET variables.

But there are some drawbacks. If you invoke URLs of your application in your javascript code, you have to insert the session id there. Also, if there are external links, the session id can be made available via the referer (sic) HTTP parameter to third parties, which could result in potential session stealing. You have to be extra careful with XSS holes. You probably have to be careful with session fixation happening during the login procedure of your application. And so on.

Avel
+1  A: 

my primary user base has static ip addresses (companies)

So, if one persone in MegaCorp (with all the same browsers, and the same external IP address) logs in, everybody there is logged in? Don't do it.

And another reason: all iPhones in the same area (same proxy, same browser) are logged in. All I have to do to break in is just to be within several hundred meters (to some kilometers in some places) to someone with access, and it's automagically granted to me.

There are in general 2 ways to have a 'passwordless login' (which is where most of these questions originate):

  • Cookies with a sufficient 'unguessable hash' from a previous login
  • Convince the user to install a certificate you can validate over HTTPS.
Wrikken
Is there any other unique identifiers I could use that php has access to?
payling
Nope, cookies and/or SSL certificates.
Wrikken
OK, both of what I'm about to suggest are probably insane next to just using cookies or certs. But for the sake of discussion, in theory, couldn't you: 1) hand out an 1x1 image with no-cache or short expiry HTTP headers whose filename is the hash you'd stick in a cookie or 2) hand out an image with uniquely identifying info inside the image data (or possibly even the dimensions) which was verified via AJAX on return?
Weston C
When using cookies, why the cludge preventing a session, and when not: you'd rely on javascript or the like for the cookie (which should be posted/getted back), when you could equally use a (hidden) post field in a form or a get variable?
Wrikken
Well, both the methods I'm suggesting could conceivably be used to recognize a user even when they navigate into a point in the application via an arbitrary url, which is something hidden form fields and stuff passed through the query string can't do. But I agree, the amount of hoop jumping we're talking about here is ridiculously high compared to just using cookies/sessions.
Weston C
A: 

Most of the $_SERVER variables are attacker controlled (remote_addr is pulled directly from the tcp socket and there for cannot be spoofed or otherwise tampered with). However an attacker can change the user-agent to anything.

Don't re-invent the wheal. session_start() and the $_SESSION super-global is secure, easy to implement and robust. To use this you should always call session_start() in a header file for all pages.

if(!$_SESSION[logged_in]){
    header("location: login.php");
    die();//Yes php keeps executing so you need this!
}

then in login.php:

if(login($_REQUEST[user],$_REQUEST[password])){
    $_SESSION[logged_in]=true;
}
Rook
Im sorry, I guess I'm not being clear. I want to simulate what cookies do (allowing users to close there browser and come back later without needing to log back in) except using database to store the "cookie". Sessions work well (and is what I currently use) for content as long as the browser is not closed.
payling
@payling so you want a session that works *indefinitely* and is only destroyed when the browser closes? By the way storing the session id in the database is very bad, it could be obtained with sql injection and then used to authenticate.
Rook
I didn't realize the remote_addr feature could not be spoofed... This helps! Now that I know this.. I could have it so the remote_addr + ip is stored upon login. when the user logs back on i can search through the users table untill it comes across a match for that value and that'll be the user...
payling
@rook I sanitize all my input post / get for numbers and letters only. That should take care of sql injection.. correct me if im wrong.
payling
@payling the remote_addr is the ip address of the browser. This value can change during a session if they are using a load balancer or if they change wifi networks. I'm not sure how this helps you at all or how this is different from a normal session. You could store infomration about the user in `users` table and access it when they login. You could access the data using a primary key stored in `$_SESSION[user_id]`.
Rook
@payling no, you can have still sql injection that is alpha-numeric. `mysql_query("select * from users where id=".$_GET[id])` you could do a `0 or true limit 1` to access the 1st row int he db (which is probably the admin). You should use parameterized quires to stop sql injection or use escaping with `mysql_real_escape_string()`, `addslashes()` is more common but less secure. Ether way you have to make sure the variable is encased with quote marks, thats why parameterized quires is more fool proof.
Rook
@payling I'm still unsure how this differs from a normal session and why `$_SESSION` doesn't solve your problem.
Rook
All true, I currently use addslashes but I'll look into escape string. I don't allow queries like the one you suggested to be accessed by the user but I get the point.
payling
My original goal was to find enough unique identifiers (host ip, host browser, etc) encrypt it and store as a cookie_auth in users table. Next time the user visits the site (after closing the browser - session destroys) I could use the $_SERVER to get ip, etc. to retrieve from user and compare to stored key to pull up his account info.
payling
@payling Well md5() isn't an encryption function its a message digest. Encryption implies that there is a method of decryption and hashes are 1 way. So you need to obtain information about a user BEFORE he logs in? Because after he is logged in you can just save his user_id and access it normally.
Rook
@payling if you do a `setcookie()` and give it a time value then the cookie won't expire when the browser closes, and the time could be like 50 years. But this cookie should be a large random number not the md5() hash of attacker known/controlled data. You can use this to generate the value: `md5(uniqid(mt_rand(),true))`.
Rook
What is the point? Someone could just copy that cookie to their computer and use it?
payling