I've read a lot of things about authentication in CouchDB, especially regarding the Cookie Authentication.
I'm still making some tests and all seems working well, for instance with this command :
curl -vX POST $HOST/_session -H 'application/x-www-form-urlencoded' -d 'name=foo&password=bar'
I get a Cookie that I can use.
But my point is, anytime I see think kind of sample on the Web, the username and password are always sent in plain text.
I'm really new to security but what's the interest of the Cookie Auth method if I first have to send my credentials in clear ?
Is there a way to send at least the password hashed ?
With something like that IDK :
curl -vX POST $HOST/_session -H 'application/x-www-form-urlencoded' -d 'name=foo&hashed_password=hashed_bar'
Cheers
Arnaud
If you send your password hashed than all the attacker needs to know is your hashed password so it wouldn't solve the problem of sending your password in cleartext - now you would have a problem of sending your hash in cleartext.
Also remember that even if that solved the problem you would still be sending your cookie in cleartext being vulnerable to session hijacking.
(There's also the HTTP digest access authentication but not without its own problems - but CouchDB didn't support it last time I checked anyway.)
What you should do is to always use HTTPS for any authenticated CouchDB access with any network involved, except maybe the 127.0.0.0 network.
(And yes, pretty much all of the examples on the web and in books show using basic or cookie authentication over HTTP which in my opinion is a disaster waiting to happen.)
Using Https is the right answer.
I'll add a clarification on the importance to compute a hash on the server side.
The hash is a one way function transforming the input into the key value stored in the server. If someone hacks the server and gets the hashed input (key value) he won't be able to deduce the input value from it to impersonate you.
If you compute the key value on the client side and no one way tranformation is performed on the server, it is equivalent to store passwords in clear text. Someone who managed to get a copy of the key value stored on the server can easily impersonate you by simply sending the key value.
Thus applying on the server side a cryptographically secure one way function (i.e.sha256) with a salt/random seed on the submitted password is required to secure the password database.
Obfuscating the sent password by hashing it, in addition to hashing it on the server side, won't help mutch if the sent hashed value is always the same. However spying data sent through an SSL connection is not trivial.
There is however a significant benefit to hashing password on the client side. A brute force attack on the server by trying to guess the password using a common password dictionary would become hopeless because the hashing on the client side randomized the password.
We may add some salt to the hash to protect against use of hashed password dictionary. When the user typed his user id, ask for the user specific salt value to the server. Then use the returned salt or hash seed value to generate the hashed password on the client side.
Brute force password guessing maybe hindered on the server side by increasing the time interval between retries. But this generally works for one specific connection. The attacker may reconnect after every two attempts. It is then required to keep track of ip addresses to recognize such type of attacks.
As of version 1.1, CouchDB, supports API access via HTTPS. Instead of using an HTTPS proxy, you can use HTTPS directly, protecting passwords transmitted over the wire. See the Feature Guide for 1.1.
Related
I'm using scrypt to generate strong hashes of the password of the user. I want to log the user in, but don't want to send the password in plaintext over the wire, how do I check if the password is correct (without a roundtrip), since it is salted?
I'm having a client / server scenario. The client is an application on a desktop computer (not a website, nor http server).
How can I achieve this? I came only this far: I'm generating the the salt + hash on the client, form a mcf out of it and send it to my server. Save the mcf to the database. I haven't send the password, just the hash which is practically useless (since scrypt should be quite strong, and would require a few million years to reverse it).
How can I now log the user into my service, without sending the plaintext password to the server to compare it? I can't rehash it, since it would result in a different hash due to a different salt? I would need to send the salt to the client, hash the password, send the hash to the server, compare it, and send some authentication token back.
How can I achieve this? Is an authentication token actually secure? It can be simply used to impersonate anyone, I guess?
don't want to send the password in plaintext over the wire,
Good idea, but if the connection is not encrypted (something like SSL/TLS), then whatever you send is plaintext. If you hash a password client-side, and send it over the network, then THAT is the password. Some would say that there is no benefit here, but it does prevent the user from exposing their actual password, which they probably re-use on other sites. (read more here)
Ideally you would use something like SSL/TLS to encrypt the connection. I guess if that wasn't possible, using asymmetric encryption with certificates on the message itself that you are sending would be an ok way of re-inventing the wheel, but I am hesitant to recommend that without having a security person look over it. It's very easy to screw up, and the rule is never roll your own crypto scheme.
If you can't verify/invalidate/update the public key, then it is not a good scheme.
I would need to send the salt to the client, hash the password, send the hash to the server, compare it, and send some authentication token back
The salt isn't supposed to be super secret, but it's not great to just give it away like that, especially to unauthenticated users. The authentication token, hash, salt, etc can all be intercepted if the connection is not encrypted. Even if they couldn't, you didn't solve the problem of users creating accounts through this method (maybe you don't need to, but it is worth mentioning).
You have to use asymmetric encryption where only the server can decrypt the data.
There is no short answer to your question, because there are so many pitfalls that can happen if you do it wrong. But as Gray says, you do need TLS protection.
I have two sources that give you detailed explanations on the right way to do this if you want to do client side scrypt processing.
Method to Protect Passwords in Databases for Web Applications. If you do not want to understand all the rationale, just jump to section 4 to see the implementation (where PPF = your scrypt).
Client-Plus-Server Password Hashing as a Potential Way to Improve Security Against Brute Force Attacks without Overloading the Server.
They are slightly different solutions but based upon the same ideas, and either should be good enough for you.
I'd like input on this cookie password storing security system,
When the user ticks the remember me box, it stores these cookies:
User name in plain text.
Password encrypted with a completely random key that the server stores in the database, that is never passed to the client and is user-specific, changes with every login.
And the server then decodes the password with the encryption key when needed.
An attacker could steal somebody else's cookie and then be logged in without having to know the actual password. They would just send the same cookie and would get in. Being able to sniff traffic off the wire and then resend it later is a replay attack.
The best defense is to use SSL so the security is end to end. If you're running a serious commercial site then you should use SSL, no ifs ands or buts. Using SSL cookies will always be encrypted over the wire so it doesn't matter quite so much what their contents are as the attack vector changes from packet-sniffing to having to read the cookie off end users' hard drives.
If your site is not quite so serious, then read on.
On my site, I take the user's password and concatenate their IP address plus a secret token and hash all of those. That hash is stored in a cookie. Then to authenticate them on the server I recalculate the hash and verify that the one they sent matches.
This ties the cookie to a particular IP address so it cannot be so easily reused by a third party. It also eliminates any danger of decrypting the cookie and discovering the password since the hash (SHA256, say) is one-way and cannot be reversed.
Also, I hope you are not storing raw plaintext passwords on your database. You are storing password hashes, yes? And are also salting them to prevent rainbow table attacks?
No offence intended, but why do you want to reinvent the wheel?
Many have already implemented their own versions of this particular wheel so why not search SourceForge? Reusable software - can you code this more quickly than you can find an acceptable (and tested) solution?
Use off the shelf building blocks for the grunt work and move on to the interesting parts ;-)
Per #caf, adding this as an answer:
If you're going to go down this path, where the cookie basically stores the server's secret, there's absolutely no reason for that secret to have anything to do with the user's password. The client can't interpret the meaning/value of that data anyway.
To the client, it's just random data since it doesn't know the key
To the server, it's no different from any other data that is
Unique to the client, and
Secret to the server
To an attacker, it's neither more, nor less random (or similarly, hard to brute-force) than a random number of equal bit length.
In essence, that encrypted data is just an authentication token with special rules for how the token was generated. But making the token the user's encrypted password only adds more risk, because now if an attacker somehow gets the encryption/decryption key from the server, they have your user's password. You've made the token itself an attractive target since it has intrinsic value.
So instead of storing the encrypted password in the cookie and the encryption key in the database, you could just have the server generate a sufficiently long random number and store it in both the DB and the cookie. Since it has no meaning to the client anyway, it doesn't really matter what you use for the token, as long it's random, hard to guess and the server can verify it. Don't bother making it have a correlation with the password.
As Leonix said, this is probably better left to someone else who has developed it before and fixed all the bugs. Especially because it's security related.
Other than that, a glaring flaw I can spot is lack of authentication, or susceptibility to a 'replay' attack, where someone just blindly sends the cookie data that they could of copied from whom they want to impersonate.
I noticed that most sites send the passwords as plain text over HTTPS to the server. Is there any advantage if instead of that I sent the hash of the password to the server? Would it be more secure?
This is an old question, but I felt the need to provide my opinion on this important matter. There is so much misinformation here
The OP never mentioned sending the password in clear over HTTP - only HTTPS, yet many seem to be responding to the question of sending a password over HTTP for some reason. That said:
I believe passwords should never be retained (let alone transmitted) in plain text. That means not kept on disk, or even in memory.
People responding here seem to think HTTPS is a silver bullet, which it is not. It certainly helps greatly however, and should be used in any authenticated session.
There is really no need to know what an original password is. All that is required is a reliable way to generate (and reliably re-generate) an authentication "key" based on the original text chosen by the user. In an ideal world this text should immediately generate a "key" by salting then irreversibly hashing it using an intentionally slow hash-algorithm (like bcrypt, to prevent Brute-force). Said salt should be unique to the user credential being generated.
This "key" will be what your systems use as a password. This way if your systems ever get compromised in the future, these credentials will only ever be useful against your own organisation, and nowhere else where the user has been lazy and used the same password.
So we have a key. Now we need to clean up any trace of the password on the clients device.
Next we need to get that key to your systems. You should never transmit a key or password "in the clear". Not even over HTTPS. HTTPS is not impenetrable. In fact, many organisations can become a trusted MITM - not from an attack perspective, but to perform inspections on the traffic to implement their own security policies. This weakens HTTPS, and it is not the only way it happens (such as redirects to HTTP MITM attacks for example). Never assume it is secure.
To get around this, we encrypt the key with a once off nonce.
This nonce is unique for every submission of a key to your systems - even for the same credential during the same session if you need to send it multiple times. You can reverse said nonce (decrypt), once it arrives in your own systems to recover the authentication key, and authenticate the request.
At this point I would irreversibly hash it one last time before it is permanently stored in your own systems. That way you can share the credential's salt with partner organisations for the purposes of SSO and the like, whilst being able to prove your own organisation cannot impersonate the user. The best part of this approach is you are never sharing anything generated by the user without their authorisation.
Do more research, as there is more to it than even I have divulged, but if you want to provide true security to your users, I think this method is currently the most complete response here.
TL;DR:
Use HTTPS.
Securely hash passwords, irreversibly, with a unique salt per password. Do this on the client - do not transmit their actual password. Transmitting the users original password to your servers is never "OK" or "Fine". Clean up any trace of the original password.
Use a nonce regardless of HTTP/HTTPS. It is much more secure on many levels. (Answer to OP).
Since it's over HTTPS, it's definitely just fine to send the password without hashing (over HTTPS it's not plaintext). Furthermore, if your application is depending on HTTPS to keep it's content secure, then it's useless to hash the password before sending it over HTTPS (i.e. if an attacker can unencrypt the data on the wire, you're screwed anyways)
No, in fact this would be a vulnerability. If the attacker is able to obtain the hash from the database, then he could use it to authenticate without needing to crack it. Under no circumstance should a user or an attacker be able to obtain a hashes password.
The whole point of hashing passwords is to add an extra layer of security. If an attacker is able to obtain the hash and salt from the database using SQL Injection or an insecure backup then he has to find the plain text by brute forcing it. John The Ripper is commonly used to break salted password hashes.
Not using https is a violation of the OWASP Top 10: A9-Insufficient Transport Layer Protection
EDIT:
If in your implementation you calculate a sha256(client_salt+plain_text_password) and then calculate another hash on the server side sha256(server_salt+client_hash) then this is not a serious vulnerability. However, it is still susceptible to eavesdropping and replaying the request. Thus this is still a clear violation of WASP A9. However, this is still utilizing a message digest as a security layer.
The closest thing i have seen to a client-side replacement for https is a diffie-hellman in key exchange in javascript. However, this does prevent active MITM attacks and thus is till technicality a violation of OWASP A9. The Authors of the code agree that this is not a complete replacement for HTTPS, however it is better than nothing and better than a client-side hashing system.
Sending a hash over the wire completely defeats the purpose of the hash, because an attacker can simply send the hash and forget about the password. In a nutshell, a system that athenticates using a hash in clear text is wide open and can be compromise with nothing more than network sniffing.
The password in plaintext show never (not even when using HTTPS) leave the client. It should be irreversibly hashed before leaving the client as there is no need for the server to know the actual password.
Hashing then transmitting solves security issues for lazy users that use the same password in multiple locations (I know I do). However this does not protect your application as a hacker that gained access to the database (or in any other way was able to get his hands on the hash) as the hacker could just transmit the hash and have the server accept it.
To solve this issue you could of course just hash the hash the server receives and call it a day.
My approach to the issue in a socket-based web application I'm creating is that on connection to the client the server generates a salt (random string to be added before hashing) and stores it on the sockets variable, then it transmits this hash to the client. The client takes the users password, hashes it, adds the salt from the server and hashes the whole thing, before transmitting it to the server. Then it's sent to the server which compares this hash to the hash(hash in the DB + salt). As far as I know this is a good approach, but to be fair I haven't read a lot on the topic and if I'm wrong about anything I'd love to be corrected :)
Disclaimer: I'm by no stretch a security expert-- and I'm posting with the hope that others will critique my position as overly cautious or improvable and I will learn from it. With that said, I just want to emphasize that hashing when it leaves your client doesn't mean you get to don't have to hash on the backend before putting it in the database.
Do both
Do both because:
Hashing on the ride over helps cover vulnerabilities of transport, if SSL connection is compromised, they still can't see the raw password. It won't matter in terms of being able to impersonate authorized users, but it will protect your users from having their passwords read in association w/ their email. Most people don't follow best practice and use the same password for many their accounts, so this can be a serious vulnerability to your visitors.
If someone, somehow was able to read passwords from the database (this does happen, think SQL injection), they still won't be able to execute privileged actions impersonating users through my API. This is because of hash asymmetry; even if they know the hash stored in your DB, they won't know the original key used to create it and that's what your auth middleware uses to authenticate. This is also why you should always salt your hash storage.
Granted, they could do a lot of other damage if they had free rein to read what they want from your database.
I just want to emphasize here that if you do decide to hash the key before departure from your clients, that isn't enough-- the backend hashing is, imo, much more important and this is why: If someone is intercepting traffic from your client, then they will see the contents of the password field. Whether this is a hash, or plain text, it doesn't matter-- they can copy it verbatim to impersonate an authorized client. (Unless you follow the steps which #user3299591 outlines, and I recommend you do). Hashing the DB column, on the other hand, is a necessity and not at all difficult to implement.
Use HTTP Digest - it secures the password even over http (but best useage would be http digest over https)
Wikipedia:
HTTP digest access authentication is one of the agreed methods a web server can use to negotiate credentials with a web user (using the HTTP protocol). Digest authentication is intended to supersede unencrypted use of the Basic access authentication, allowing user identity to be established securely without having to send a password in plaintext over the network. Digest authentication is basically an application of MD5 cryptographic hashing with usage of nonce values to prevent cryptanalysis.
Link: http://en.wikipedia.org/wiki/Digest_access_authentication
If you want to see a "real life" use, you could look at phpMyID - a php openid provider that uses http digest authentication http://siege.org/phpmyid.php
.. or you could start from the php auth samples at http://php.net/manual/en/features.http-auth.php
Http digest rfc: http://www.faqs.org/rfcs/rfc2617
From my tests all modern browsers support it...
If you're looking to replace a clear-text password over HTTPS with a hashed password over HTTP then you're asking for trouble. HTTPS generates a random, shared transaction key when opening up a communication channel. That's hard to crack, as you're pretty much limited to brute forcing the shared key used for a (relatively) short-term transaction. Whereas your hash can be just sniffed, taken off-line and looked up in a rainbow table or just brute forced over a long amount of time.
However, a basic client-side password obfuscation (not hash) sent over HTTPS does have some value. If I'm not mistaken this technique is actually used by some banks. The purpose of this technique is not to protect the password from sniffing over the wire. Rather, it's to stop the password from being usable to dumb spying tools and browser plug-ins that just grab every HTTPS GET/POST request that they see. I've seen a log file captured from a malicious website that was 400MB of random GET/POST transactions captured from user sessions. You can imagine that websites that used just HTTPS would show up with clear-text passwords in the log, but websites with very basic obfuscation (ROT13) as well would show up with passwords that are not immediately of use.
Whether there's an advantage, and whether it's more (or less) secure really depends on implementation. There's arguably some advantage, but if you implement it poorly, you could definitely create a solution that is less secure than passing even a plaintext password.
This can be looked at from the perspective of two types of attacks-- one with access to the network traffic, and another with access to the database.
If your attacker can intercept the plaintext version of the network traffic, then seeing a hash of the password is more secure than seeing the password in plaintext. Although the attacker could still log in to your server using that hash, it would require a brute-force crack (sometimes pre-computed) of that hash to determine the password that might be useful on other systems. People should use different passwords on different systems, but often don't.
If an attacker gained access to the database, perhaps through a copy of a backup, then you'd want to ensure that one couldn't log in with only that knowledge. If, for example, you stored a hash salted with the login name as hash(login_name+password), and you passed that same hash from the client for direct comparison, then the attacker could pick a user at random, send the hash read from the database and log in as that user without knowing the password, increasing the scope of the breach. In that case, sending the password in plaintext would have been more secure because the attacker would need to know the plaintext in order to log in, even having a copy of the database. This is where implementation is key. Whether you send a plaintext password or a client-side hash of that password, you should hash that value at the server-side and compare that hash with the hash stored in the user record.
Concepts to keep in mind:
You "salt" a hash by mixing in some scope-unique value to your hash, typically row-unique. Its purpose is to guarantee uniqueness of hashes from each other even if the plaintext values they represent are the same, so two users with the same password would still have different hashes. It's unnecessary to treat a salt as a secret.
When authenticating, always hash on the server-side whatever value you pass from the client as a password (even if it's already hashed) and compare it with a pre-hashed value stored on the database. This may necessitate storing a double-hashed version of the original password.
When you make a hash, consider adding a server/cluster-unique salt to the hash as well as a row-unique salt to safeguard against matching any pre-computed hashes in lookup tables.
If you're connected to an https server the data stream between the server and browser should be encrypted. The data is only plain text before being sent and after being recieved. Wikipedia article
If you want to achieve the same reliability as when transferring over https, then yes - one option - the implementation of an asymmetrically encrypted channel at the ajax level.
If we are not talking about registration (for example, the first transmission of the password is always protected), then there are options.
For example,
The server generates a random string and generates a salt sends it to the user.
The user calculates a hash from his password and using this hash as
a key encrypts this random string with a blowfish, for example (there
is an implementation in JS for sure) and sends it back to you.
You, on your own, using the hash stored on the server, also encrypt this
random string with a blowfish.
Compare.
An attacker would have to attack the bluefish key using a random source and ciphertext. The task is not easy.
Isn't SSL/TLS replacing the nonce? I don't see added value of this since SSL/TLS also protects against Replay Attacks.
Ref.
https://en.wikipedia.org/wiki/Cryptographic_nonce
It would actually be less secure to hash the password and send it over a non-encrypted channel. You will expose your hashing algorithm on the client. Hackers could just sniff the hash of the password and then use it to hack in later.
By using HTTPS, you prevent a hacker from obtaining the password from a single source, since HTTPS uses two channels, both encrypted.
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?
Client requests salt for a user name
Client prefixes password with salt, then hashes it before sending the hash to the server
Server compares hash recieved to the one on the server for that user name
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.
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.
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.
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.
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.
I'm working on a project in which remote clients need to log in to a webserver. I'm not looking for examples in any particular language; just a general idea of the security concerns involved.
The basic question is:
How should user credentials be passed to a webserver for verification?
I'm picturing your typical website login. One field for username, and another for password. You type in both and click "Log In". What happens next?
I can imagine a few scenarios:
Credentials are sent to the server as plain text. A server-side script creates a hash of the password and compares it to the stored hash for the user.
Credentials are encrypted locally, and the result is sent to the server. The server decrypts the credentials and continues as in #1
Something I haven't thought of yet? I'm new to this. Go easy on me!
Option #1 strikes me as weak because the credentials are sent over the internet in plain text.
I see option #2 as not much better than option #1. If someone intercepts the encrypted credentials, can they not just send those to the server another time, and still manage to log in?
Any insight is appreciated.
edit: the "Related" sidebar suggests this question, which mentions a client/server handshake with a salt added to the password. Is that the right way to go?
Option 1 is by far the default. The plaintext weakness is usually overcome by enforcing SSL during the login so that the password is at least encrypted during transit.
Edit: I suggest you follow the accepted answer for that question.
Don't forget to require a nonce for your request. This will help protect you against replay attacks.
Edit the second: Wayne thoughtfully mentioned that you should salt your password before you hash. Here are some basic tips:
It doesn't matter if your salt is a prefix, postfix, or infix
Your salt should be large, random, and complex.
Your salt should be unique per salted value. The salt itself doesn't need to be encrypted.
Why not SSL the communications? Being able to observe the conversation gives me insight into your app. Encrypt the entire communication, not just the credentials.
Edit: Always use salt for a locally stored hash. Windows continues to fail as far as brute forcing locally hashed passwords because they do not salt by default.
The simplest answer is to get an SSL certificate for your server. There's really no reason to mess around with creating your own encryption techniques in this particular application. As you've noted, if the connection isn't encrypted, you leave yourself open to man-in-the-middle attacks, regardless of whether the client or the server is doing the password encryption. Encrypt the connection, and you don't have to worry about it.
On the client side you only have a browser that can render HTML and submit forms. Who's gonna encrypt stuff?
Send login and password in plain text (SSL it if you have concerns). On the server side you can do whatever you want with it (preferrably hash and salt password before storing them in the database).
You might also want to consider using multiple iterations of the hash algorithm, 1000 iterations will slow things down nicely and make rainbow tables that much harder to create