views:

257

answers:

2

I'm implementing authorization in my gwt app, and at the moment it's done in the following fashion:

  1. The user signs up by putting his credentials in a form, and I send them in clear text to the server
  2. The server code hashes the received password using BCrypt and puts the hash in a database
  3. When the user wishes to log in, his password is sent in the clear to the server, that checks it against the stored hash

Now. The thing that's bothering me about this is the fact that I'm sending the password to the server in the clear, I keep thinking that I wouldn't be very pleased if an application I was using did that with my (use-for-everything-kind) password, but encrypting it on the client wouldn't really earn me anything, since the attackers could just use the hashed password as they would the clear one.

I have been googling all day for this, and it seems the Internet is quite unanimous when it comes to this - apparently there is nothing to be gained from client side password encryption. This, this and this are just a few examples of the discussions and pages I've come by, but there are many, many more, all saying the same thing.

This question, in light of all this, might seem a bit unnecessary, but I am hoping that somewhere, someone, will have another answer for me.

What can I do, if ssl isn't an option at this point, to ease my mind about this? Is there anything to be done, or will implementing some sort of client-encrypt-server-decrypt-scheme just be time-consuming feeble dead-horse-kicking? Any ideas are welcome.

+2  A: 

If SSL isn't an option then you obviously don't care enough about security ;)

But seriously - like you mentioned, client side encryption of the password is not a good idea. In fact, it's a very bad one. You can't trust the client side for jack - what if an attacker managed to alter the JS code (through XSS or while it was sent through the wire), so that your MD5/whatever hash function just passes the pass in cleartext? Not to mention that you should be using a good, strong, salted encryption method, like bCrypt - something which is just slow on the client and like mentioned before, doesn't quite add to the security of the app.

You could try bypassing some of those problems: by sending the hash library through some secure means (if that was possible in the first place, we wouldn't have to bother with all this now, would we?), by somehow sharing a common secret between the server and client and using that for encryption... but the bottom line is: use HTTPS when possible (in GWT it's hard to mix HTTPS and HTTP) and justified (if the user is stupid enough to use the same password for your not-security-related app and for his banking account, then it's highly likely that he/she used the same password on a number of other sites, any of which could lead to hijacking the password). Other means will just make you think that your application is more secure than it is and make you less vigilant.

Igor Klimer
Thanks for your very good answer, Igor.
Banang
+3  A: 

For login, SSL should be your option, even at this point. If it's just for login, you don't need an expensive SSL farm, but at least you protect the (use-for-everything-kind) password, even though it's clear, that the remaining communication isn't secured [*]. This may mean, that you need to buy a certificate for just one login server, which can again save you a lot of money, depending on the certificate vendor.

For GWT, if you can't afford to encrypt all communication, you'll have to put the login on a separate page due to Same Origin Policy constraints.

If that still isn't an option, you can think about logging in via OpenID, just like stackoverflow does.

There can't be any secure communication over insecure media without some pre-shared secret - usually provided by the root certificates that are installed in a browser (BTW, it's funny/scary that browsers and even entire operating systems are usually downloaded via HTTP). Other systems, e.g. PGP, rely on previously established trust in a "Web Of Trust", but this is just another form of pre-shared secrets. There's no way around it.

[*] Using SSL for everything - unfortunately - comes with additional practical problems: 1) Page loads are a lot slower, especially if you have many elements on the page. This is due to SSL-induced round trips and the resulting latency, which you can't counter with even the fastest SSL farm. The problem is mitigated, but not fully eliminated by keep-alive connections. 2) If your page includes elements from foreign, non-HTTPS sites (e.g. images inserted by users), many browsers will display warnings - which are very vague about the real security problem, and are therefore usually unacceptable for a secure site.

A few additional thoughts (not a recommendation)

Let's assume the worst case for a moment, i.e. that you can't use SSL at all. In that case, maybe surprisingly, hashing the password (with a salt) before transmitting it, may actually be a bit better than doing nothing. Here's the reason: It can't defeat Mallory (in cryptography, a person who can manipulate the communication), but at least it won't let Eve (a person who can only listen) read the plaintext password. This may be worth something, if we assume that Eves are more common than Mallorys (?) But note, that in that case, you should hash the password again (with a different salt), before comparing it with the database value.

Chris Lercher
Thanks for the extensive answer, a lot of useful links in there. I appreciate it!
Banang