0

I have recently been challenged with coming up with a Login framework which holds user data in a separate database which I connect via a SOAP connection. Now, I have done something along these lines before using only MySQL.

Now to come up with the login system, I store the user info returned in $_SESSION variables; They return the password in plaintext (along with some other information) - not sure why - however, I do not store that password in plaintext; rather I encrypt the password with an unique key for each user.

To check if the user is currently connected I use their sessions using 2 different parameters hashed together and compare to the logged_in__string which is done at log in; this is the basic setup:

$_SESSION['logged_in__string'] = hash ( 'sha512', 'USER_PASSWORD' . $_SERVER['HTTP_USER_AGENT'] );

After I create that, I encrypt the password using an unique key for each user; Then create a new function, check() which will decrypt the password, and create the hashed value compare it to the $_SESSION['logged_in__string'] and if equal then user is logged in.

My interest is in the $_SESSION variables. What are some potential risks in the approach I have taken, and if there are any, what are some good methods to secure these sessions for the user.

3
  • Interesting, I do use HTTPS, no, the user types his password, and session is established by default only for that session; however, the user can remained logged forever (checking the login box). So you are saying, I should be safe from a session hijack? @Anders
    – Sam
    Oct 26 '17 at 21:27
  • 2
    Sounds to me like you're trying to sprinkle magic crypto dust on your application. Encrypting passwords instead of hashing is a big no-no, and as @Anders said it doesn't seem like you gain any benefit from it anyway. Oct 26 '17 at 21:34
  • @AndrolGenhald so what should I do? Simply setting $_SESSION['logged_in'] = true?
    – Sam
    Oct 26 '17 at 21:36
2

Hash your passwords

First of all, it sounds like the database stores password in plaintext. That is very, very, very bad. See this question for how to do it right.

The problem with your system

Now, to your actual question. The aim of your system is to stop session hijacking. However, it does nothing of the sort. If I steal one of your users session cookie and send it in a request to your server, how would you know it was stolen? All your system does is decrypt the password the real user provided at logg in and check that it is correct, which it always will be. Your system basically boils down to checking that password = password with some "magic crypto dust sprinkled on top" (to quote Androl Genhald).

To see this, write down your system in simplified pseudo code and then go through how the server would behave in case of an attack with pen and paper. I find that is a useful technique for problems like this.

A bit besides the point, but: Only using one round of SHA-256 is not enough for hashing passwords. And storing the encrypted data and the key at the same place is not a good idea.

The solution

Keep it simple:

$_SESSION['logged_in'] = true

Then, to protect against session hijacking, you can do the following:

  • Use good HTTPS.
  • Make sure your session IDs have sufficient entropy.
  • Mark the session cookie as secure and HTTP-only.
  • Watch out for XSS.

Your system also makes sure that the user agent stays constant during a session. This is only limited protection since the user agent can be easily spoofed, but it might help against an unsofisticated attacker. If you want to keep that check, simply store the original user agent in the session and then at every request check that the user agent header is the same as the one you have stored.

4
  • 1
    Thanks for the answer, I just wasn't sure setting a single $_SESSION variable would be sufficient, I always thought I had to perform some thorough check. Just a few thoughts, 1 the database setup is really out of my hands; I'm not sure if they store the password in plaintext, I know they return the password to me in plaintext. 2 I'm doing 3 of your suggested fixes, I have HTTPS, session IDs are renewed, and all cookies are set httponly and secure. 3 I do not store the key, I assign a random value to an user, and at each login a new value should be released. Again, thank you very much.
    – Sam
    Oct 27 '17 at 9:16
  • 1
    No problem! As for the database - I understand it might not be possible for you to change, but if they can return the passwords to you in plain text they are doing it very wrong. Passwords should not be encrypted, they should be hashed.
    – Anders
    Oct 27 '17 at 9:23
  • I understand, and when I built my system on MySQL I hashed them with a salt, I first encrypted it with a hex encryption, then hashed it... I could never decrypt it myself, but that was never a problem since really didn't need to see the password.
    – Sam
    Oct 27 '17 at 9:32
  • 1
    @Samuel Just an fyi on your terminology: hexadecimal is an encoding, not encryption; the main difference being that you don't need a secret key to decode it. Encrypted data can be encoded as hex for a variety of reasons, but if something is hex it isn't necessarily encrypted. Oct 27 '17 at 13:55

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.