8

For a rich client web app, on the server I need to verify that each call comes from a legally logged in user. Obviously user ID is not enough, because that's easy to guess.

I have an idea I am skeptical about, but can't think of rational reasons not to do it.

Is using password hash protected with a sufficiently strong hashing function (bcrypt?) a good session identifier? It already is in DB, is unique for each user and cannot be guessed easily. I am using a secure channel (HTTPS) for all communications between the client and server, so I don't have to worry about eavesdropping on the session identifier.

I don't care about session expiration, state or being logged in from two computers at a time. The server app is stateless enough. All I really need is user ID and some extra means of verification that he has logged in properly.

D.W.
  • 98,420
  • 30
  • 267
  • 572
Konrad Garus
  • 755
  • 1
  • 7
  • 8
  • 1
    Hi @Konrad, is this not the same question as your other question from earlier today, http://security.stackexchange.com/questions/4936/what-to-transfer-password-or-its-hash ? What is the difference to you? – AviD Jun 30 '11 at 18:07
  • 1
    It's completely different. That one was whether It's better to send password or hash on authentication over an insecure channel. This one is about using password hash for identifying an open session over a secure channel. What are the possible risks? Should I avoid sending hash to client and using it this way? – Konrad Garus Jun 30 '11 at 19:24
  • 1
    @Konrad - ah, I see your point: your questions stem from certain assumptions, leading you to believe (in your point of view) that these are conceptually different; since I claim your assumption basis is faulty, they equivilate (in my PoV) to pretty much the same thing. I'm not meaning to be condescending here (and sorry if it seems that way), but this explains why the *questions* are in fact different, even if there is a single answer for both. Am I correct in understanding your meanings? – AviD Jun 30 '11 at 19:28
  • 1
    Can you explain which assumptions are faulty? I agree they are very similar, but I don't think they have the same answer. Secure authentication over insecure channel is different from session maintenance _over secure channel_. What I'm trying to find here is whether having this kind of key is secure - the fact that it's static, as well as that it's directly related to password management. – Konrad Garus Jun 30 '11 at 19:39
  • 1
    @Konrad, the answers here + my answer on the other question pretty much explain that. Point is, its not just *not* secure, it adds no value and the hash becomes a replacement for the password. – AviD Jun 30 '11 at 19:57
  • 1
    Right, and my question is: What exactly is insecure in using this specific kind of session key for secure channel? Is it only the fact that it's not temporal? – Konrad Garus Jun 30 '11 at 20:00
  • 1
    I'm confused. You say you don't care about state, but then you say that the state has been established: the user has been identified and authenticated and a secure channel has been setup. It seems like you are using the fact that the secure channel has been set up to keep state. – this.josh Jul 01 '11 at 00:25
  • 1
    @Konrad, as I said - this hash effectively *becomes* the new password. Just as you wouldn't think of using a the password as a session key, you shouldn't use the constant hash of it either. So, yes, the non-temporal aspect is definitely a big part of the problem, but there are other issues too. – AviD Jul 04 '11 at 09:20

4 Answers4

14

One problem you could have with this kind of setup is, from what you've said, it looks like the session token would be static (ie for a given user, it never changes, until they change their password). As such if an attacker manages to get access to a token for a given user (trojan, keylogger, packet sniffing (if SSL isn't used) etc), they will have persistent access to the application.

Also you'd need to be more careful than usual to ensure that session tokens aren't logged anywhere server-side as they'd essentially be as good as passwords.

Rory McCune
  • 60,923
  • 14
  • 136
  • 217
  • 1
    This is a good point, but... If they are able to install a trojan or keylogger on client, there's little difference between capturing a password on login and capturing the hash (or session ID) later. – Konrad Garus Jun 30 '11 at 19:32
  • 2
    +1. Imagine an XSS vulnerability where attackers can easily exfiltrate your session IDs. In most systems, the session ID changes over time, so exfiltrated sessions keys won't work after the user logs out -- they have a short lifespan. But if you re-use the same session keys on every request, then lifespan is much longer. The attacker just has to wait for that user to log in again, and then they can easily steal the session. – Mark E. Haase Jul 01 '11 at 15:34
  • 2
    @Konrad, your point about passwords is somewhat valid, but consider that the password typically gets transferred ONCE per session, while the session ID gets sent with every single request. Therefore, the session ID is much easier to steal than the password. – Mark E. Haase Jul 01 '11 at 15:35
  • @mehaase Good points (both of them). I think my thick client with TLS is invulnerable to XSS. For a determined attacker, capturing one request is not much more difficult than capturing more of them (and that's not a problem with TLS). – Konrad Garus Jul 01 '11 at 15:46
  • Anyway, the point about gaining permanent access and having more places to secure (not just one request handler) makes much sense. – Konrad Garus Jul 01 '11 at 15:48
7

I don't know what libraries you are using for writing your application, but most provide some sort of session management.

The implication of using a password hash a session token, you will not be able to tell one session from another. And what if two users have the same password? Will you be able to tell the difference?

Further, you will make yourself vulnerable to replay attacks, unless you choose to add some random data to the session token. This you must store in a persistent storage somewhere.

When you already have gone this far, you should choose to generate the whole session token, since you already need i.e. a session table.

For a HTTPS channel, anything goes as long as no one is able to read your cookies (remember https only cookies!) or guess them.

Dog eat cat world
  • 5,759
  • 1
  • 27
  • 46
  • I don't care about one session per user. Hash is not the only user identifier - I also pass user ID for some other reasons. There's no cookies, it's a rich client. This is also the reason why reusing a session mechanism is more difficult. Replay attacks are just as possible with session ID. And I assume HTTPS is there. – Konrad Garus Jun 30 '11 at 17:02
  • As for session management, you can choose to transfer the session id's with other methods than cookies, but the same security implications will apply, independently if its a rich or thin application. – Dog eat cat world Jun 30 '11 at 17:10
  • 1
    Right, the only difference between rich client and browser client, is that the browser will automatically send the cookies on each request - whereas (I assume) you need to explicitly force the rich client to send the session details. – AviD Jun 30 '11 at 18:09
  • @AviD Right. I was replying to the "use a library for sessions" point. The main question is not how session works, but whether this kind of ID is secure. – Konrad Garus Jun 30 '11 at 19:30
3

A good session cookie will prepend an expiration to the serialized data and then prepend an HMAC of the expiration + serialized data to the expiration + serialized data using the application's secret key.

message = serialize_to_bytes(session_data)
random = random_bytes(16)
expiration = unix_timestamp_as_16_bytes(now + 2 * 60 * 60 /*2 hours*/)
signable = random + expiration + message
signature = HMAC-SHA256(application_key, signable)
signed_message = signature + signable

The signed_message will be unforgeable. It will be subject to replay attack for 2 hours. If the signed session cookie is hacked within the 2-hour window, the session could be infinitely extended. To do better, you would need to come up with a good scheme for nonces. In a large application with multiple web servers serving session cookies, that would require a central database of used nonces, which can be unwieldy.

Be sure to set the cookie's secure flag (so that it only is sent in HTTPS requests) and httponly flag (so that it is not available to JavaScript directly).

Be sure to use SSL always.

yfeldblum
  • 2,807
  • 20
  • 13
3

The proposed approach strikes me as a poor approach. Let the web framework do session management for you. Many web frameworks will already provide support for user authentication and will let you, in a single call, query whether there is a logged-in user associated with the session of the current request. Just use that. Rolling your own is dangerous. I don't understand why you need or want to roll some special-purpose mechanism for this.

D.W.
  • 98,420
  • 30
  • 267
  • 572
  • Right. I wouldn't do it with browser-based client. I'm talking about a rich desktop client which does not really use HTTP. I know the difference between SSL and session management. Mentioned it only to prevent answers talking about channel security. – Konrad Garus Aug 03 '11 at 07:27
  • 1
    A rich desktop client doesn't seem like it changes anything substantial. There's still no way to specify a particular session key for HTTPS. As far as I can see, the proposal mentioned in the question doesn't make sense and can't be implemented. – D.W. Aug 03 '11 at 21:18
  • @JoóÁdám, thank you. Based on Konrad's response, you were totally correct: I had misunderstood what scheme he was proposing. I have edited the question to clarify it, per Konrad's comment, and I have edited my answer to remove the problematic statements. Thank you for noticing this and helping us to set it straight! – D.W. Sep 22 '15 at 15:53