Re: Plaintext passwords?
by maverick (Curate) on Mar 22, 2002 at 20:43 UTC
|
The way I typically handle it is to.
- store them crypted
- require that the login page be accessed via SSL
- forgotten password is reset and emailed ONLY to the email address stored in the database for the provided user id. This doesn't prevent a malicious person from resetting someone else's password, BUT the person who receives the email saying what the new (randomly generated) password is, is the valid user.
/\/\averick
perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"
| [reply] [Watch: Dir/Any] |
|
That all sounds good. I assume that once someone logs in successfully via SSL, you send them a cookie, and they continue using that over an unsecured connection? In that case, the cookie essentially becomes the user's password. Do you have a good solution for preventing the bad guys from capturing and reusing that cookie?
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
Re: Plaintext passwords?
by FoxtrotUniform (Prior) on Mar 22, 2002 at 20:17 UTC
|
Unfortunately, storing the crypted version of the
password on the server means that the client has to send
the password to the server in plaintext. Either you hide
that with SSL, or you accept the fact that you have no real
security.
If you try to protect the password in transit by using
something like HTTP digest authentication, then you have to
store the password (or some equivalent secret information)
in plaintext on the server. Which is the bigger
vulnerability?
Some excellent points, no_slogan. It's kind of
depressing that the current state of the art, as far as
anything common enough to be useful goes, relies so much
on plaintext passwords. (Although you might be able to
get the client to hash the password before sending it over
the wire, using a browser plugin of some sort. Provided
that you trust the plugin.)
Is there a better way of doing user authentication for
sites like PerlMonks out there that doesn't rely on
pie-in-the-sky technology? (Preferably something that
doesn't involve shared secrets, which IMHO are just too
much trouble.) Having the client hash the password before
sending it over the wire is a start, but doesn't help much
if the server isn't who the client thinks it is, since the
attacker can just play back the password hash at the real
server.
I'd look up some ideas, but my copy of Applied Crypto
is at home, and I'm not. Anyone else?
--
:wq
| [reply] [Watch: Dir/Any] |
|
Having the client hash the password before sending it over the wire is a start, but doesn't help much if the server isn't who the client thinks it is, since the attacker can just play back the password hash at the real server.
That's why HTTP digest authentication includes a variable "nonce" value. The server sends the nonce to the client when it first attempts to access the page. The client calculates the hash of the password and the nonce together, and sends that back to the server. The server verifies that the hash it recieved was calculated with a valid password and a nonce that was actually sent to that client recently.
If someone tries to replay an old password hash, the server won't accept it, because it won't have a valid nonce.
If the nonce used contains some (cryptographic) function of the time and the client's IP, you can avoid the problem of having to have the server remember which nonces are valid.
The problem, of course, is that the server has to have the password in plaintext so it can calculate the hash and see if it matches the one it got from the client.
| [reply] [Watch: Dir/Any] |
|
How about this:
- Store the hashed password on the server.
- Hash the password on the client (using Javascript
PasswdMD5 or something), then cat on a sufficiently
random session ID and hash it again. Send that hash
to the server.
- The server takes the session ID, cats it onto its
copy of the hashed password, hashes the result, and
compares that hash to the one it got from the client.
So the server isn't keeping around any plaintext
passwords, and the session ID acts as a one-time key to
prevent replay attacks. For extra tasty goodness, you
can do this through SSL to prevent attackers from
sniffing the session ID, although unless they know the
original password hash (which, since we're not storing
the password in plaintext anywhere, is mildly unlikely)
the worst damage they could do with a sniffed session ID
is chuck a bogus hash back at the server and give the
real user a "sorry, try again" message (if that).
I'm a bit leery of this system, because it seems too
simple. Can you see any problems with it?
Update: Cacharbe expressed some doubts about
the "sufficiently random" session ID. Basically, the
idea is that the server picks a random integer (from
/dev/random or something similar), keeps a
copy, and sends it off to the client. Client hashes
their password, cats the session ID onto the password,
hashes _that_, and sends it back over the wire. Server
cats the (same) session ID onto its hashed password for
whoever the client claims to be, hashes it, and checks
it against the hash it got back from the client.
The problem with this (which I only just saw --
augh!) is that the server's still storing information
that can be used verbatim to attack a client account.
If I can get the hashed password from the server, then
I can just connect, get a session ID, and go from
there. In short, it isn't really a step up from storing
passwords in plaintext on the server. Oh well, back to
the drawing board.
--
:wq
| [reply] [Watch: Dir/Any] |
Re: Plaintext passwords?
by cacharbe (Curate) on Mar 23, 2002 at 14:19 UTC
|
I know I'm coming late to the dance with this, but I've been giving it some thought. When we speak of security, we are usually talking about one or two different things; authentication and encryption. The http protocol isn't really designed for security, it is designed for functionality. Security is left to the implementor.
Putting aside https for the moment (which really is the best implementation of http when it comes to both of these topics) we need to look at what we can do to fulfill both of these points.
In the case of a login, we are actually in the process of trying to authenticate our user, which means there isn't a trust system in place between the two parties.
My thought about this would be that when a user first subscribes to our system, they are required to provide they're public key. Also, the monks public key is provided on the site. Now, when someone logs in, they first encrypt their pass-phrase (We're talking security here, so let's go all the way) with the monks public key, insert it into the pass-phrase text area and submit.
PM has its private key, decrypts the pass-phrase and registers it. And, of course, monks must repeat this cycle if they must login. Of course we can still use our current cookie method of remembering who we are to limit the need for this. Beware, however, if we are at a location that doesn't have a tool for encryption, we won't be able to login. If a pass-phrase is lost, a new one can be generated and emailed to the monk using their public key. The system is complete.
Another way would be to write an encryption method (using the above mentioned key structure) completely in JavaScript, send the PM public key in the client side scripting. OnSubmit, encrypt the pass-phrase, set one of your inputs (hidden or otherwise) to the encrypted password and away you go.
Sounds trivial, but I'm not sure I would want to try and write those algorithms in JavaScript of VBScript. *BLECH*
This brings me back to https. This protocol has the two pieces of security that I mentioned above. The authentication portion of https is a safeguard against some site saying they are PM when they're really not and stealing whatever informaiton we are sending to one another. The simplist method of encrypting passwords would be to implement the login only in https without a third party certificate. All we are truly talking about here is encrypting passwords and sending them securely, not authenticating one or both of the parties involved. On most webservers you can allow the server to generate it's own certificate for the sake of encryption, and only if we were going to implement a shopping cart or something similar would the need for a third party cert really be necessary.
Those are just some thoughts I've had about this topic, your mileage may vary, this offer only good to the first ten callers, some restrictions may apply.
C-.
| [reply] [Watch: Dir/Any] |
|
If a pass-phrase is lost, a new one can be generated and emailed to the monk using their public key.
That would be really cool except for one little problem: what happens if I forget the password to my private key? I used to do that regularly, because I didn't decrypt messages very often.
Now, when someone logs in, they first encrypt their pass-phrase with the monks public key, insert it into the pass-phrase text area and submit.
You need to prevent someone from capturing and reusing my encrypted password, too. See my comment on nonces elsewhere in this thread.
Of course we can still use our current cookie method of remembering who we are to limit the need for this.
If you do this, my cookie essentially becomes my password, because anyone who has my cookie can make the system think he's me. Cookies are stored in plaintext on the user's computer. Cookies are sent across the network in plaintext. Not good for security.
Beware, however, if we are at a location that doesn't have a tool for encryption, we won't be able to login.
I think this is a deal-breaker for most web apps.
| [reply] [Watch: Dir/Any] |