11

I've got a novice question -

It is often said that you should not store plaintext passwords in a client-side cookie. (I'm imagining a web browser cookie, but I supposed this applies in general.) But in simple web apps we often store a plaintext session-ID in a cookie.

To elaborate, we often secure sites using this model:

  1. The user enters username and password on the client machine. These are sent to the server over a secure (HTTPS) connection.
  2. The server hashes the password and validates against the database. Assuming the password is correct, the server generates a session-ID and returns it to the client machine alongside the body of the response.
  3. The client stores the plaintext session-ID in a cookie. Every time the client makes another call to the server, the session-ID is sent back to the server over a secure connection.
  4. After x minutes of inactivity, the session expires and the session-ID is no longer considered valid for that user.

But we're strongly discouraged from using this model:

  1. The user enters a username and password on the client machine. These are stored, in plaintext, in a client-side cookie. Then, they are sent to the server over a secure (HTTPS) connection.
  2. The server hashes the password and validates against the database. Assuming the password is correct, the server returns a response.
  3. Every time the client makes another call to the server, the password is sent back to the server over a secure connection.
  4. After x minutes of inactivity, the cookie expires and the password is no longer saved on the client's machine.

Why is the second model considered insecure while the first model is secure? Granted, in the second model a nefarious cookie-reader could steal the password from the browser. But in either model a nefarious key-reader could steal the password from the IO subsystem. Is this the only reason that the second model is not used - to slightly decrease our attack vector by blocking cookie-readers? Or is there some larger problem with storing the password on the client, which I'm not seeing?

2 Answers 2

17

Several points against the second model:

  • Hashing the password should take a significant amount of time, so as to slow down brute forcing in the event of a database leak. Checking a password on every request is a waste of resources.
  • Cookies can be vulnerable to XSS attacks, and having your password stolen is worse than having your session stolen (passwords aren't changed as often, and they tend to be reused on multiple sites).
  • Cookies are generally stored unencrypted on the client.
  • Sessions can't be easily invalidated, as it requires changing the password.
  • It's completely incompatible with any Single Sign-On system (thanks @CBHacking)

Storing the password hash instead of the password isn't much better, you solve the performance problem but you're still potentially leaking the password hash to be brute forced, and you can't easily invalidate sessions, or even tell them apart in the case of a user with multiple concurrent sessions.

5
  • Even with storing the password hash if someone steals the cookie they have access to the server until the user changes the password, which is potentially a very, very long time. If an attacker steals a session token then the attacker has access until the token expires. Typically, no more than 24 hours and often much less than that. If using a stored password an attacker could do malicious things without ever logging in. Depending on the app's logging that could be very interesting. Feb 4, 2019 at 23:48
  • 1
    Most people reuse passwords across services. So a password stolen from a relatively insecure service can be retried on other services potentially to steal data. Losing your stack exchange password may not be critical but if you have reused this password or some form of it in a financial website, you may lose money as well.
    – Ashutosh
    Feb 4, 2019 at 23:52
  • 1
    This system also just flat-out doesn't work with any kind of SSO system, where the service provider (the website you are using) should never see your credentials; those only go to the identity provider (Google, Facebook, Microsoft, etc.) or else any service provider could impersonate you on any service that uses the same identity provider. It's a bad idea for sites that handle their own authentication too, though (as the answer and other comments pointed out).
    – CBHacking
    Feb 5, 2019 at 1:12
  • 1
    Good answer. I would also cite an economic reason: there is a vibrant black market for stolen passwords but next to no market for stolen session cookies, as they become useless before they can be sold.
    – John Wu
    Feb 5, 2019 at 1:13
  • I'd like to add, that in case of shared use of the client browser, the password is much more likely to be leaked, if the temporary browser data is not purged locally. A session token usually does not allow for password changes and only gives timed access to the account in question. A password would lead to permanent loss of the account. Feb 5, 2019 at 6:24
2

Completely agree with the previous answer. Here is a bit more context to help you assess the security of your solution.

Your first model is pretty much the typical session management with cookies. It supports all primary use-cases required of sessions.

Your second model is somewhat similar to Basic Auth, except that the authentication data could be exposed to the clients via leaking cookies (not setting the HTTPOnly flag). If the HTTPOnly flag is set you are very close to Basic Auth, sharing most of its properties: no reliable timeout, missing SSO support, leaking passwords, no multiple sessions, etc.

I put together a Web Authentication Guide to help decide which auth schemes fits best your use-cases. Check it out!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .