Question

A company I know is in discussions to firm up its password security policy across all its web application products.

Right now they are sending username / password authentication in POST forms over HTTP, and thus, they are being sent plaintext.

The simplest solution to the problem is simply to require HTTPS for logon across all our applications, right?

Well, there's some internal discussion about instead doing some kind of roll-our-own client-side encryption of passwords (password + salt, etc.).

Is there an accepted HTTP-only solution?

Opinions are like... well, everyone has an opinion, so I'm looking for credible security literature that can support your recommendation. Don't just google and send me to a blog post... I've already done that and further.

I have found OWASP's recommendations: http://www.owasp.org/index.php/Top_10_2007-A7#Protection

As well as Microsoft's: http://msdn.microsoft.com/en-us/library/aa302420.aspx

EDIT: Giving your recommendation for using SSL isn't enough. I need some kind of supporting documentation. I KNOW that rolling our own client side encryption is bad. I need to be able to credibly sell that to co-workers and management.

Also, HTTP Digest has been mentioned. Seems nice, but Digest is ONLY for HTTP authentication, and not for data sent over POST.

Was it helpful?

Solution

+1 to Mehrdad's answer. Going ahead with home-grown cryptography is risky.

Speaking from experience here, after having seen vulnerabilities in home-grown client-side encryption solutions. Most of the vulnerabilities are due to the same reason - the data transfer was protected by encryption with a secret key, but the key itself was exchanged in an insecure manner.

TLS/SSL solves the problem of not just secure key exchange, but also of secure data transfer.

TLS/SSL protects your sensitive information by using assymmetric key cryptography to exchange the symmetric key used to encrypt information back and forth, once the TLS/SSL session has been established. The symmetric key is generated at runtime, and is a shared secret between the client and the server; it is this key that is used to encrypt all other traffic once the session is ready for transfer of data.

The server's public and private keys are used only to exchange this shared secret. The only known way to compromise the shared key is to compromise the server's private key (so that the secret key can then be decrypted). In reality, it requires negligence or malice on the part of the server administrator.

If you roll your own encryption solution, you must exchange the symmetric key, in a secure manner. The easiest way to do so is to use TLS/SSL; the harder way is to implement your own assymmetric key exchange cryptography solution.

OTHER TIPS

I highly recommend against going with your own solution (in security sensitive environments). Go with SSL. It's a proven technology and it's easy to implement.

Rolling your own security solutions can be really dangerous and even if it's implemented properly (0.000001% chance), it will be expensive.

If the data itself isn't too sensitive, but the passwords are, I'd suggest using HTTP digest authentication (which is quite a different beast from HTTP basic authentication). It's is quite secure over straight HTTP, and not at all difficult to implement on the server. Nothing is sent over the wire that could reveal what the password is, just information that allows the client to demonstrate to the server that they have the correct password.

If you want a decent explanation of how to implement HTTP digest authentication in your application, Paul James has an excellent article on it.

The only real problem with HTTP authentication is in the browsers themselves: the UI is terrible, but that can be overcome with some Javascript.

You can store the passwords securely by storing the A1 hash.

UPDATE: As mentioned in other answers, while the server can avoid MITM attacks by not accepting Basic auth, the client is still vulnerable because it will.

UPDATE: You can't secure data over POST unless you either (a) do encryption in JavaScript on the client or, (b) do everything over SSL.

You can, with a little bit of magic, use HTTP auth with forms. The article I linked to above is called 'HTTP Auth with HTML forms', after all. But that won't be done over POST.

If you really need it do use POST, use SSL and salt the passwords in your database.

If you want avoid CSRF, I recommend using formkeys, though the idea goes by many different names, I picked up that name from hacking Slashcode for my own use a few years back, which is where I came across it first.

You'll spend more time and money rolling your own solution and not be assured that it's secure. Industry standard SSL is easy to implement and far more secure out of the box than you can afford to make your own solution.

time == money

Buy a certificate and spend your time working on your application instead of a secure login form.

Client-side encryption is helpless against most MITM attacks. Attacker can simply remove your script.

It will only protect against passive sniffing. If that is good enough for you, you can use:

  • Hashing implemented in Javascript. It's easy to implement challenge-response for initial login, but don't forget that for attacker session cookie is almost as good as password (you'd have to limit login to single IP and/or use script to generate one-time cookie for every request, which I imagine would be difficult and brittle solution).
  • HTTP Digest authentication. More secure, as it can use one-time hashes, mutual authentication, etc., but standard UI is absolutely repulsive.

...just use SSL.

HTTP only solutions will always be susceptible to man-in-the-middle attacks.

EDIT: A network trace would be an easy way to prove that HTTP isn't secure.

Okay, here's the only answer you need: Your BANK only supports login/auth via SSL. If there was a better way to do it, they would.

Well, there's some internal discussion about instead doing some kind of roll-our-own client-side encryption of passwords (password + salt, etc.).

The first thing we need to address is data in transit vs. data at rest. From the OP it sounds like the big concern is username/password in the clear over the Internet. So, you really care about data in transit. HTTPS via SSL is a tested method of doing this (and it's a pretty easy fix!). Now, if you really want to roll your own for data at rest (in a db, on a file server, etc.), that's a different beast, but the existing methods for data encryption are going to be better than a roll your own.

Relying on the client side for your security is bad. Period. In a corporate environment, yes, you can somewhat rely on a standard setup. But, ultimately, users are dumb and you may run into someone disabling javascript or whatever client based solution you roll out, so they end up sending the username/password in plain text anyway (even if your servers dont' know what to do with it because it's not in the expected format.

Roll-your-own is not going to be subject to the scrutiny that an existing solution has. You could end up adding additional security issues into the mix because of the code.

We just put out a web/mobile app to do some of this stuff. It creates random URLs for logins, using HTTPS and a hashed/AES encryption method for the database storage. Theres a simple JSON API to use it without our UI, heres our writeup, give it a look.. http://blog.primestudiosllc.com/security/send-time-limited-secure-logins-with-timebomb-it

you mentioned doing your own encryption plus salt... I suggest using javascript md5 (it's also used by yahoo on their non ssl pages, or so he claims)...

And you double hash the password... some may argue that double hashing it would make it prone to collision attacks. I would have to disagree because people have been able to do till now md5 signature collisions only on files, where large amount of data is md5'ed...

If it's a big corporate website (and there would be reasons to break in) there is no excuse not using SSL.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top