13

I have TLS connection between my server and client. I have no certificate, so the connection is susceptible to the Man-in-the-middle attack.

I fear that attacker could intercept the password hash and use it to authenticate himself in my application.

What is the best way to transmit password hash? To use server nonce or client nonce? And what hashing algorithm should I use?

  • 3
    I presume that the exact attack scenario you're worried about is: "I've self-signed a certificate and I'm concerned that if someone gets my CA, they can impersonate my server and stage a MITM." Is that your scenario? Or do you inherently distrust all CAs? – Naftuli Kay Jan 27 '15 at 21:18
  • Is the client a proper application, or a website? In the first case you can simply act as your own CA. – CodesInChaos Jan 28 '15 at 9:51
27

You should look into Certificate pinning.

This is effectively allowing you to trust your self-signed certificate, and that server certificate only from your client by a hard lookup of the public key of the certificate. So the chain of authority is not followed (which is where a self-signed certificate falls down) and instead the public key is validated by the client application to be trusted directly.

You should not look at hashing, or anything else on the application layer as it will be inherently susceptible to a MITM attack.

| improve this answer | |
  • 1
    Well, you should hash, just on the server side and to protect the password in storage instead of in transit. – cpast Jan 28 '15 at 3:16
  • @cpast It's usually recommended to hash on the client side so that the password never gets sent over the wire in the first place (encrypted or otherwise.) In a ideal setup, the server should never actually know the password, but only its hash. – reirab Jan 28 '15 at 17:15
  • +2 for the first 2 paragraphs, -1 for the last paragraph. :) You definitely should hash passwords, but that concern is orthogonal to the need for verifying that the server really is who it says, which is solved by the suggestion in your first two paragraphs. – reirab Jan 28 '15 at 17:17
  • 2
    @reirab: The 3rd paragraph was in the context of defeating a MITM. If you send a hashed password over the networking application layer, the hashed password effectively becomes the password. I'm not saying that hashing is a not a useful concept at all if that is the impression you got? – SilverlightFox Jan 28 '15 at 17:26
  • 4
    @reirab No, it's just about always recommended to hash on server side. You always need to hash on the server side anyway, because otherwise the hash is your password, and a compromise of the database compromises your site credentials. The server gets the password and immediately verifies it; no administrator can see that password, unless they modify the code of the webpage to save the password elsewhere. – cpast Jan 28 '15 at 18:32
27

You can't.

There is no secure way to transmit it if you can't authenticate the server and establish a secure channel. If you can't authenticate the server then you can't be sure if you are talking to the server or the attacker. Hence, even if you use TLS to establish a secure channel, it doesn't protect you at all since you could be talking to the attacker while thinking that you are talking to the server.

The certificate is essential. Without it, or some knowledge of the public key of the server, you cannot be sure that you are really communicating to the server as an attacker could act as a man in the middle between you and the server.

TLS use Diffie-Hellman for the key exchange. If you look at the security section of the wikipedia page you will find the following attack which is exactly what you are vulnerable to.

In the original description, the Diffie–Hellman exchange by itself does not provide authentication of the communicating parties and is thus vulnerable to a man-in-the-middle attack. Mallory may establish two distinct key exchanges, one with Alice and the other with Bob, effectively masquerading as Alice to Bob, and vice versa, allowing her to decrypt, then re-encrypt, the messages passed between them.

Conclusion

You need to have a valid certificate to be able to authenticate the server or you will be vulnerable to man in the middle attack. An easy way to achieve that is to include the server certificate in your application which is also known as certificate pinning.

| improve this answer | |
  • 4
    I was thinking of answering with the lines of "Ditch your unreliable TLS", but you did it better. – Mindwin Jan 28 '15 at 15:03
13

Bundle your self created root CA certificate with your application and configure it to reject all untrusted certificates. If you only use your own CA cert, this is arguably more secure than relying on the normal CAs, since CAs have been compromised in the past by attackers, and are subject to government authorities and politics as well.

Rolling your own authentication scheme is foolhardy, and is almost guaranteed to be less secure than simply using TLS with a bundled certificate.

| improve this answer | |
  • Indeed. Recognize your own root cert. If you get anybody else's cert, trust chain or not, IMMEDIATELY reject it as invalid. No bypass option. (Oh, and set the expiration date for the root cert to the highest allowed value by X509 format.) – Joshua Jan 28 '15 at 17:00
  • Can i revoke and reissue this certificate if it gets compromised? – Igor Jan 29 '15 at 10:24
  • 2
    @Igor Yes, but you have to put the revocation list in the cert when you create it, and you have to put certificate revocation support in your app blog.didierstevens.com/2013/05/08/… – Steve Sether Jan 29 '15 at 15:47
2

Since others have already mentioned about TLS authentication and what can be done regarding that problem, I'll just focus on:

What is the best way to transmit password hash?

MITM is one of the threats in your scenario. Another possible (also very common) threat is a Data breach. You must consider the case where your database might be compromised and must take necessary precautions on the server side as well. Hashing passwords on the client-side is not a very good idea, unless you do not trust the server with your passwords and you are hashing them again on the server. I guess it is not the case with your scenario because the server is your own.

If the password hashes, sent by the clients, are stored as-is in the database, an attacker can impersonate all users by sending the server the hashed passwords from the database as-is. Hashed passwords will merely serve as secret access tokens in this case. Read this for more details.

And what hashing algorithm should I use?

Some good hashing functions (for storing passwords on the server) include bcrypt, scrypt and PBKDF2. Take a look at Thomas Pornin's awesome answer for why these are better. Basically, these functions, if used properly, will make the task of an attacker much more difficult in case of a data breach.

| improve this answer | |
  • "Hashing passwords on the client-side is not a very good idea..." Can you expound on this assertion? Under what scenario is there any drawback to hashing on the client side? Also, what need does the server have to ever know a user's password in the first place? Transmitting the password to the server, even encrypted, is still opening up more possible vectors for the password to be compromised. What benefit offsets this disadvantage? – reirab Jan 28 '15 at 17:24
  • @reirab: The link in my answer already does that (edited my answer anyways :-)). If the hashed password database is compromised (in case of just client side hashing), those hashes will merely act as an Access Token. These token can be then used to authenticate to the application. – Rahil Arora Jan 28 '15 at 18:19
  • The most upvoted answer in your link recommends hashing on both sides... – reirab Jan 28 '15 at 18:37
  • 1
    Yes. Indeed. The point is, you must hash on the server side no matter what. Since the OP asked for recommendations regarding hash functions, that's what I included in my answer (since other answers didn't cover that). – Rahil Arora Jan 28 '15 at 18:54
1

Use SRP (Secure Remote Password) mechanism of TLS.

The client and server authenticate each other based on knowledge of a shared password which is never sent (this means that whatever you use as password -in this case the hash- will have to be stored in plaintext by the server).

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.