15

I am making a login script that I would like to be as secure as possible. Problem is, security seems to be a never ending battle. So essentially, I am looking for suggestions and improvements to my ideas.

What I have is a login based solely on sessions. Anytime the session information changes, session_regenerate_id() is called to avoid obvious hijacking attempts.

When the session is not set, I check a cookie for valid login, and on success, I update the session.

I attempt to secure the cookie by adding a hash value along with a piece of unique user information (like username or id). This hash is comprised of various information, including the username/id, undecipherable password hash, part of the IP address, etc. By extracting the username/id from the cookie, I can make a new hash from the valid user information and compare that with the hash in the cookie. My hopes here are to prevent fake cookies and cookie hijacking (unless they also spoof the IP address).

EDIT Assume that the login itself will be done via HTTPS/SSL, so the transfer is (reasonably) secure.

Am I on the right track? What else can be done to secure my login?

Thanks for the help!

Simon Hayter
  • 3,131
  • 27
  • 53
steveo225
  • 11,394
  • 16
  • 62
  • 114
  • http://phpseclib.sourceforge.net/ – Teson Mar 25 '11 at 16:14
  • Thats actually very nice to know for future security related topics (just bookmarked!), but I am assuming that if the transfer is to be secured, then SSL will be used. I am more looking for ideas to secure the state of the login to prevent unauthorized entry via unethical means. – steveo225 Mar 25 '11 at 16:17
  • 1
    How about using SSL? At the end of the day, if the attacker is on the same network and is sniffing, I don't think having all those help, and SSL isn't exactly unbreakable too, but at least it's not plaintext. My 2c – Andreas Wong Mar 25 '11 at 16:21
  • You shouldn't be binding the session to the IP address unless the user specifically asks you to do so. – user229044 Mar 25 '11 at 16:25
  • 1. I am only binding to part of the IP address 2: Why not? (Note the hash, which contains the IP part, is done such that I cannot decipher the IP address, or any other component in the hash, therefore, I cannot use the information in any attempt to track them). – steveo225 Mar 25 '11 at 16:28
  • Because a thousand different users might be behind a same router / proxy and will give you the exact same IP Address. It's not about whether it's obfuscated enough. – Andreas Wong Mar 25 '11 at 16:31
  • Yes. I work has us behind a proxy and I noted that moving around (physically) still keeps me logged in. However, it does help prevent a large number of attackers, as they would have to be on your network then to hijack your cookie. What can be done to prevent that? – steveo225 Mar 25 '11 at 16:37
  • Use SSL, seriously, anything transported between your server and your client in PLAINTEXT is insecure and no amount of obfuscation can help you. And just FYI, free public wifi is a lot out there, I don't see what's stopping them to be "on your network then to hijack your cookie". – Andreas Wong Mar 25 '11 at 16:43
  • I get it. I have stated twice, my question isn't about the trasfer from the browser to the site, for that SSL _will_ be used. My question is how to secure the **state** of the login after the fact to prevent hijacking, fake credentials, etc. – steveo225 Mar 25 '11 at 16:47
  • For that you might wanna have a look at http://en.wikipedia.org/wiki/Cross-site_request_forgery and http://en.wikipedia.org/wiki/Cross-site_Scripting – Andreas Wong Mar 25 '11 at 16:50
  • That is exactly what I am attempting to prevent. The hash blocks most forgeries because the attacker would have to guess a ciphered password, and anytime a cookie login is done, it is validated against the known information before creating a session. From that point on, the session is used. So, how can the cookie and session be secured more than I have? – steveo225 Mar 25 '11 at 16:56

5 Answers5

6

Stop what you are doing. Do not check the user-agent or the ip address. The user-agent is an attacker controlled variable and checking this value does not increase the security of this system. The ip address will change for legitimate reasons, such as if a user is behind a load balancer or TOR.

A session id must always be a cryptographic nonce. In php just call session_start() and then start using the $_SESSION super global. PHP takes care of all of this for you. If you want to improve php's session handler, use the configurations. Enable use_only_cookies, cookie_httponly and cookie_secure. Also setting the entropy_file to /dev/urandom is a good idea if you are on a *nix system but if your under windows then your in trouble.

For instance to authenticate a user:

//In a header file
session_start();
...
if(check_login($_POST['user_name'],$_POST['password'])){
   //Primary key of this user
   $_SESSION['user_id']=get_user_id($_POST['user_name']);
   $_SESSION['logged_id']=True;
}

And to verify if a user is logged in:

//in a header file
session_start()
...
if(!$_SESSION['logged_id']){
   header("location: login.php");
   die();//The script will keep executing unless you die()
}

To improve this system read OWASP A9 and use HTTPS for the entire life of the session. Also read OWASP A5: CSRF aka "session riding" and OWASP A2: XSS because they can both be used to compromise a session.

Simon Hayter
  • 3,131
  • 27
  • 53
rook
  • 66,304
  • 38
  • 162
  • 239
  • That's all great, and for the most part exactly what I am doing. But what about the cookie? I use this to remember login between sessions so the user doesn't have to login 5 separate times a day. – steveo225 Mar 25 '11 at 19:31
  • @steveo225 `session_start()` creates a cookie for you. You can change the expiration time by configuring php. – rook Mar 25 '11 at 19:32
  • Yes, I realize that, but I do not want to set an expiration time that last for days... or even a couple weeks. – steveo225 Mar 25 '11 at 19:36
  • @steveo225 An expiration time is required by the platform because its a vulnerability if you don't have one, its called an immortal session. Keep in mind that this value can be brute forced, and there isn't a rate limiter or even logs for this. – rook Mar 25 '11 at 19:39
  • Thats my point. I don't want the sessions to last that long, so I use a cookie to "refresh" the sessions, as a means to keep the use logged in for, well, as long as I deem fit. So, from what I can tell, I am doing nearly everything correct to keep the session protected and the login details maintained, however, I want to make a "secure" cookie that is extremely difficult to copy, forge, hijack, etc. – steveo225 Mar 25 '11 at 19:45
  • @steveo225 There is no point in just encrypting the username/password if you spill the session id. This is an OWASP violation and its exploitable with firesheep. It also makes having a long session timeout an even worse idea. – rook Mar 25 '11 at 21:53
  • I don't follow you. How am I "spilling" the session id? Also, I don't have a long session timeout, that is *exactly* what my last comment was about. The cookies are for retaining login over a longer time and I want them to be secure. – steveo225 Mar 25 '11 at 23:05
  • @steveo225 Funny, my biggest complaint about SO is when the OP doesn't read the links provided. Read about `cookie_secure` and owasp A9. – rook Mar 26 '11 at 00:34
  • Is there a `cookie_secure` for normal cookies (e.g. those set via `set_cookie`)? Or is that just for the cookie the session id is set? I can only find anything on `cookie_secure` with regards to sessions, and those aren't the cookies I am refering to. – steveo225 Mar 26 '11 at 00:55
  • Also, I am using httponly and secure on the cookie. I wasn't blowing off your links, but I have already pointed out that it should be assumed HTTPS/SSL is used. – steveo225 Mar 26 '11 at 00:58
3

There is no such thing as secure cookie UNLESS it's transmitted over SSL only. It can be mitigated some when using a persistent non-session cookie (like remember me), by doing exactly what you're doing, but not in the same way you're thinking of doing it.

You can indeed store server variables such as the user-agent, the ip address and so forth (and even JavaScript variables), but they are only good for validating that the persistent cookie data matches the client's new connection. The ip address isn't a good idea except when you know that the client (like you only) isn't going to change on every page load (a la AOL).

Modern web browsers and 3rd party services like LastPass can store login credentials that only require a key press (and sometimes not even that) to send the data to the login form. Persistent cookies are only good for those people who refuse to use what's available otherwise. In the end, persistent, non-session cookies are not really required anymore.

  • 2
    Ok, so basically, I can do things to obfuscate the cookie and make it harder to forge, crack, duplicate, etc., but in the end, if the user chooses "remember me" it is really their responsibility to be safe if the connection is not secure, and there is nothing I can do about it... – steveo225 Mar 28 '11 at 12:35
1

I use a cookie based method (using setcookie function) but ....

session_start();
...
if(check_login($_POST['user_name'],$_POST['password'])){
   //Primary key of this user
   $_SESSION['user_id']=get_user_id($_POST['user_name']);
   $_SESSION['logged_id']=True;
}

...these methods are wrooooong !!!!

I crack my website with an attack based on the cookie.

  1. I used cookie option of the WebCruiser vulnerability scanner, so I get my cookie after login.
  2. Then I changed a simply value on cookie
  3. Then I clicked save cookie.
  4. At this point I clicked on webbrowser see on the left panel then I clicked right then I clicked on refresh page, so I got my admin page without using the login page with user and password.

So if someone push you a virus to read the cookie history of IE or Firefox, you'll be happy to find out your admin user and pass can be used by others.

So how to fix the problem? Simple: combine the cookie with session server or session's cookie with sessions server, or session with file session, or cookie with file session.... will be secure but slow :((((

0

SESSION more secure than cookie and my advise is to create a unique id for the current login attempted like :

$id = uniqid();
$_SESSION['username'.$id] = "something ...";
Ali Al-Naimi
  • 728
  • 7
  • 11
  • wouldn't a session with an indexed user id handle this (through the unique session id that's automagically created?) – Snowburnt Sep 28 '13 at 12:11
0

I keep all login data in the users session, this way its all stored server side.

The only thing i would store in a client cookie is stuff like 'auto login', 'session id'

dbers
  • 636
  • 5
  • 16