views:

192

answers:

5

Situation 1 - Connecting the server to the database:
Its always said that passwords should not be stored in plain text, however to connect to the mysql database requires the password, in plain text it seems... I'm guessing the best solution to this is to store it in an encrypted form, decrypt it in my app as needed and then erase it from memory (SecureZeroMemory in windows I guess so the compiler cant optimise it out).

Situation 2 - Users logging into the server from a remote computer:
As for users passwords my plan is to never actually store the original password at all. Instead I will store a randomly generated "salt", for each user, prefix there password with it then hash it, which seems to be a relatively common way. However I don't have an SSL connection available at this point, so I'm guessing the plain text passwords could be intercepted, what's a good solution to this?

What are good algorithms (links to C/C++ implementations would be handy as well if you have them) for doing this, a look on the net comes up with 100's of them?

EDIT:
If I got SSL, would the following be secure (assuming a strong hash algorithm is used), or should a different method be used?

  1. Client requests salt for a user name
  2. Client prefixes password with salt, then hashes it before sending the hash to the server
  3. Server compares hash recieved to the one on the server for that user name
+1  A: 

You are correct that if you're not using SSL then the passwords can be intercepted.

It is common practice to never decrypt a user's password, so keep it stored hashed with a salt and when the user types in their password you will add the salt and hash it, comparing it with the stored, hashed password. This will allow you to never have the decrypted version of the password every.

You really should look into securing the connection so that the password is secure when the user types it in.

Update to answer edited question:
If you have the communication secured using SSL you can still use any number of extra measures of security you like including hashing the password. As added security it is a good idea to remember that the password you store should be stored hashed with a salt. That salt should be kept safe and never be accessible anywhere except by your application. This way when the user submits the password you just add the salt and hash and you compare that version with the stored version.

Brendan Enrick
The thing is even hashing it client side, although a hacker couldn't get the users password (which they may use elsewhere so thats good), the hacker can still log straight into my server using the intercepted password packet.
Fire Lancer
You are correct about that, which is why you want to have the secure connection. It makes it slightly harder. Keep in mind that there is no such things as "completely secure". Information is only safe if no one knows it and it isn't recorded anywhere.
Brendan Enrick
Ok, so what if the server randomly generated a public and private key for each connection and sent the public one to the client, the client then encrypts the password and any other data using it. Only the server would be able to decrypt, and the private key is tied to that specific socket connection. I assume that way even if someone identified the password packet, apart from breaking the encryption the packet is useless to them, they couldn't just send it to the server and get logged in ?
Fire Lancer
The attacker could still perform a man in the middle attack - he intercepts your log in requests, initiates a log in, gets the public key, generates another key pair, sends you the generated public key, gets your encrypted password, decrypts the password using the generated private key, encrypts the password using the public key from the server, and logs in. This schema is missing authentication of the server.
Daniel Brückner
It's not true that password can be intercepted if no using SSL. Almost all databases use some kind of hashing to protect passwords.
ZZ Coder
A: 

Not sure if this is what you are asking for. But a simple PHP example using the built in sha1 function:

// Check the hashed password from the database
if (sha1($salt.$password) == $providedPassword)
{
    // User is authenticated
    return TRUE;
}
else
{
    // User is not authenticated 
    return FALSE;
}

One thing you could do is also hash the password with javascript before it is sent over the wire. The question is how is the salt string shared between client and server? One possibility is to use a session variable. And then use the session variable to unhash the password afterwards on the server. This would mean that the man in the middle would need to know one other piece of info to make sense of the password. Not as secure as SSL, but perhaps an extra layer of defense against casual network sniffers.

I could also imagine a hashing scheme linked to some sort of captcha system used to salt the password on the local client before sending over the wire. The client would be providing the text for the salt string by completing the captcha. You could look it up on your end.

The main concern is the man in the middle not understanding the plain text password.

SSL should be used, but the above techniques might be useful where SSL is not possible.

Gordon Potter
Storing a salted hash helps if the database is compromised, but does not protect against sniffing the plain text password on wire at all. Hashing on the client and just transmitting the hash is bad in the same way - just get the hash from the wire and send it to the server when ever you like. A solution would be to try to include a time stamp or another secret in the message send to the server, but this is not possible because the server only knows the hashed password and cannot use the password to verify the time stamp or secret. Just storing the hashed (and salted) password is simply to
Daniel Brückner
weak to provide the required level security. A secret shared between server and client is required to provide this and to avoid storing the secret on the server you will have to establish it when connecting ... well, in the end you require exactly what SSL provides.
Daniel Brückner
Maybe I wasn't clear in my explanation. There are two layers. Storing the hash password in the database, and hashing the plain text password by the client before sending it over the wire. The server side would then have an extra step of unhashing the sent password. But you are right in that the shared salt/key is the trick. It seems like using some other piece of data could be used such as a captcha. Perhaps the captcha used could be mapped to a specific numeric code, but the actual captcha text used to produce the salt string would be provided by the user and can be looked up on the server.
Gordon Potter
I do agree SSL is the best solution, and you are right this is basically a description of roll you own ssl and as such is NOT advisable for high security needs.
Gordon Potter
"unhashing the sent password" generally the idea of a hash is its one way, you sure you don't mean encrypt the password on the client and then decrypt it on the server?
Fire Lancer
sorry encrypt/decrypt is what I meant. Sorry for the terminology mixup.
Gordon Potter
+1  A: 

Connecting the server to the database

Just storing the database password in the server - encrypted or not - is a bad idea. It is obvious storing it in plain text, of course. And if you just store it encrypted, the server still needs the key to decode it. It is usually not very hard to find the key in the server code. The best solution is to let the user starting the server enter the password and store it nowhere. Alternatively - and probably even better - you can store all sensitive information - for example database users, passwords, and so on - encrypted and let the user starting the server enter a master key to decrypt this information.

Connecting a user to the server

This is really a hard problem and easy to mess up. A quote from this great article article on the topic I absolutely recommend reading.

No, really. Use someone else’s password system. Don’t build your own.

A good solution might be using the Secure Remote Password Protocol.

Daniel Brückner
Is there a C/C++ implementation of SRPP that can be used given a TCP connection without an SSL certificate?
Fire Lancer
A: 

Newer MySQL uses hashed password over the wire, so you don't have to worry about man-in-the-middle.

If you worry about the password stored in your configuration file, you can encrypt the configuration file with a password. However, the problem is that you have to enter a password to start your application.

I wrote a similar application over 15 years ago. Back then, PGP was my choice. I am not even sure it's still around.

ZZ Coder
Sending hashed passwords over the wire is not secure - the attacker can get the hash and use it to authenticate later. He doesn't get the plain password, but can still log in as you.
Daniel Brückner
+1  A: 

Situation 1 - Connecting the server to the database

There isn't an easy answer here. In order to connect, the server needs the password (or symmetric key, or private key or whatever). It must get it either from the disk or some external means (like an administrator typing it at startup). Adding some indirection, such as encrypting all the sensitive stuff under a master password, can add some convenience but otherwise doesn't change the situation.

Typically, it is fine to put the password or key in a file on a server. If you do this, make sure to set the permissions on the file so that only the users that need it have access to it. This is an excellent reason to have different processes on your system run as different users, and to set up separate roles/accounts and passwords for each.

Situation 2 - Users logging into the server from a remote computer

You are headed in the right direction here, I think. What it sounds like you're asking for is a secure authentication protocol. You want one that provides mutual authentication and prevents a man-in-the-middle attack by failing if such an attack is attempted. There are many to choose from of course.

It is also worth mulling whether your authentication should operate based on "something you know" (passwords) or "something you have" (public/private keys). Assuming based on your question that what we're looking for is passwords, two that I like are SRP and Kerberos.

SRP was mentioned earlier, and that doesn't get nearly the attention it deserves. SRP has the advantage that it doesn't require the server to know the password, or key, or anything that an attacker could use to gain access. If you broke into a correctly configured server using SRP and stole all the data, you'd still need to do something like a dictionary attack on each key individually before you had anything you could use to impersonate a user.

I also like Kerberos because it is supported by tons of software (I know Postgres supports it, I've only found mentions of mysql not supporting any good authentication technology) and has a system of 'tickets' that provides a single sign on capability. Kerberos needs some other technology to help strengthen its initial authentication exchange and SRP would be great for that but I'm not sure they've done that yet. Something about it making the KDC (key server) stateful I think.

Kerberos' weakness is that you have to be more wary of the server storing the keys. While it doesn't store the passwords in plaintext, it does store the keys, which are essentially hashed versions of the passwords. And while the client doesn't exactly send either the password or the key straight over when authenticating (this is a Real auth protocol after all), it does use the hashed password as the key, and so anyone else who knows the algorithm and knows the key could do the same. We say that the server stores a "password equivalent". As a result, all the manuals tell administrators to put the kerberos services on their own separate, locked-down boxes to minimize the chance of compromising their contents.

The nice thing is, once you settle on a strong authentication exchange, other good things typically fall out of it for free. You end up with both parties sharing a mutual 'secret' that can be used once for the duration of the session, never sent over the wire, and can't be known by a third party. Want encryption? There's the key, all ready to go. This is exactly how SRP-secured SSL is defined in RFC 5054.

Charlie