2
\$\begingroup\$

In order to secure my page SESSIONS I have the following pages.

My questions are

  1. Am I over-reacting with this?
  2. Should I place the token in login.php instead of the loginForm.php ?
  3. When a user logins, I save his IP in the DB. Should I make use of this in authentication ?

Thank you community.

Login form loginForm.php

$token = md5(uniqid(rand(),TRUE));
<input name="login" type="text" class="textfield" id="login" />
<input name="password" type="password" class="textfield" id="password" />
<input type="hidden" name="token" value="<?php echo $token; ?>" />
<input type="submit" name="Submit" value="Login" />

When the user logins login.php

$fingerprint = sha1('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT'].$_SERVER['REMOTE_ADDR'].$_POST['token']);
    session_regenerate_id();
    $member = mysql_fetch_assoc($result);
$_SESSION['SESS_MEMBER_ID'] = $member['member_id'];
$_SESSION['SESS_TOKEN'] = $_POST['token'];
$_SESSION['SESS_FINGERPRINT'] = $fingerprint;
session_write_close();
    header("location: index.php");
    exit();

Authenticating on every page auth.php

    session_start();
    $fingerprint = sha1('SECRET-SALT'.$_SERVER['HTTP_USER_AGENT'].$_SERVER['REMOTE_ADDR'].$_SESSION['SESS_TOKEN']);
    if( !isset($_SESSION['SESS_MEMBER_ID']) || (trim($_SESSION['SESS_MEMBER_ID']) == '')  || ($_SESSION['SESS_FINGERPRINT'] != $fingerprint) || !isset($_SESSION['SESS_TOKEN']) || (trim($_SESSION['SESS_TOKEN']) == '') ) {
        header("location: denied.php");
        exit();
    }
\$\endgroup\$
  • \$\begingroup\$ It is not good to base your logins on IP. They change often for a large group of users. It's better to watch for user patterns and if the IP doesn't change for 6 requests - then it suddenly does - you might want to do something. \$\endgroup\$ – Xeoncross Aug 25 '11 at 19:19
  • \$\begingroup\$ Don't quote me on this but i think both IP address & .$_SERVER['REMOTE_ADDR'] can Change Especially for mobile devices, so You might be locking some users out of your application. \$\endgroup\$ – Ryan Stone Feb 19 at 2:42
4
\$\begingroup\$

1) Overreacting is a question of how valueable your protected information is. My personal oppinion is that by the nature of digital computers and of the internet there is no such thing as overreacting in security. You either want something to be public or you do not, and in the latter case there is quite a bit of work and knowledge involved to counter all the different attacks. On the other hand, a lot of other people will say that if your protected information is not really valueable enough to hackers, then probably no hardcore hacker will invest enough time so your protection might not worth your programming efforts.

2) In the code above you build your fingerprint by hashing a concatenation of different information about the remote user and the token is used as a kind of salt (in addition to 'SECRET-SALT') to make that hash unique. So the answer depends on how secure is your session storage.

If you are alone on the server or you have a secure session storage for $_SESSION (like a password-protected database), then you do not need to worry about someone reading the contents of your session variables. This also means that protecting your fingerprint by hashing it is absolutely useless, in which case you can just remove the token and hashing from your code completely. In this case you also do not need a fingerprint, you can just store the user variables separately and compare them separately.

If there is a way for your $_SESSION contents to leak, then you want to protect private information in it. In this case you will want to keep your token private and do not send it to the user, put it into login.php instead. Normally, you do not have to worry about protecting a salt because even if it is known it will increase the time considerably for a hacker to crack a password, not just because of the longer password string but also because precomputed rainbow tables become useless. But in your case you do not have a password, all you have is the user_agent and the IP, both of which are easily predictable or sniffable. This means that the concatenated information is basically no variable to the hacker, so the only thing keeping him from cracking your fingerprint are your salts. So if you reveal them, the hash becomes useless.

To sum it up: If you want maximum securty in all situations, keep fingerprinting and hashing, but since your protected string is easily guessable, keep your token private this time. Theoretically even if your token is compromised 'SECRET-SALT' will still provide protection, but only as long as your code is safe. If your filesystem is hacked or the sources for the website your are building are public you cannot rely on 'SECRET-SALT' alone. Do not depend on hiding it, 'security by obscurity' is a bad practice.

3) Generally you should not depend on the IP to stay consistent across a session. This is because for a lot of legitimate users the IP can keep changing constantly, this can be because they are behind corporate load balancing, they are using AOL or some other proxy network. A possible solution is to observe the IP of a session and if it is consistent for, say, 10 pages, then it is reasonable to assume that it will stay consistent in the future. So only then will you start making checks on it. However, storing it temporarily in a DB can still be of use, eg. for logging so that it can be analyzed what happened if there is an attack or so.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ This is a great answer. Thank you. At the end you suggest storing the sessions in a secure place is a great way. What are these places? \$\endgroup\$ – EnexoOnoma Aug 25 '11 at 10:23
  • \$\begingroup\$ Basically you have two choices to store sessions in a more secure way than the PHP default. (1) You can use the 'session.save_path' php setting to change the session files' folder to a private directory which is not shared wih a different site (and not world-readable). (2) Or you can implement your own storage functions and supply them to session_set_save_handler(). Your functins can then store session data to a passworded database or write to encrypted files etc. \$\endgroup\$ – ultimA Aug 25 '11 at 13:50
2
\$\begingroup\$

ultimA is absolutely right on his points, though security is such a large subject to cover, I would add this addenda:

Generally you want data to be private or non-private, but in the cases that you may want it private but don't need it private due to its lack of value and usefulness, there is another consideration to take in the security implementation: leakiness of the abstraction

That is to say, if the security is in such a way that everything you code has to consider and implement the security making it difficult to apply the abstraction and dry principles effectively, then ratchet it back. Unless your data's privacy is in the need category, then do your best to abstract it away but live with the misgivings.

In short, if your data is in the want privacy but not need privacy category, implement as much security as you can up to but before the point where it becomes a spider's nest to maintain throughout the whole codebase.

On another note, there is something to be said for the risk to security caused by overly difficult to implement/fragile security. If it becomes easy to make a mistake and implement the security incorrectly in one place, or downright break it on accident, then you are stepping into some risky waters.

Just my two cents, though ultimA is also spot on in his points, like I said at the beginning, security is a massive subject and how much/how little to implement can have volumes written about it without repeating the same points.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.