Thinking through why you shouldn't use plaintext passwords in authentication, even inside TLS
I recently read an article (this one, via) that advocated for just using plaintext passwords inside TLS for things like IMAP and (authenticated) SMTP. My gut reaction was that this was a terrible idea in general, but I couldn't immediately come up with a solid reason why and why other alternatives are better for authentication. So here's an attempt.
There are (at least) two problems with passwords in general. The first problem is that people reuse passwords from one place to another, so knowing someone's password on site A often gives an attacker a big lead on breaking into their accounts elsewhere (or for other services on the site, if it has multiple ones). The second problem is that if you can obtain someone's password from a site through read-only access, you can usually leverage this to be able to log in as them and thus change anything they have access to (or even see things you couldn't before).
The consequence of this is that sending a password in plaintext over an encrypted connection has about the worst risk profile for various plausible means of authentication. This is because both ends will see the password and the server side has to directly know it in some form (encrypted and salted, hopefully). Our history is full of accidents where the client, the server, or both wind up doing things like logging the passwords by accident (for example, as part of logging the full conversation for debugging) or exposing it temporarily in some way, and generally the authentication information the server has to store can be directly brute forced to determine those passwords, which can turn a small information disclosure into a password breach.
So what are your options? In descending order of how ideal they are, I can think of three:
- Have someone else do the user authentication for you, and only validate
their answers through solidly secure means like public key cryptography.
If you can get this right, you outsource all of the hassles of dealing
with authentication in the real world to someone else, which is often
a major win for everyone.
(On the other hand, this gives third parties some control over your users, so you may want to have a backup plan.)
- Use keypairs as SSH does. This requires the user (or their software)
to hold their key and hopefully encrypt it locally, but the great
advantage is that the server doesn't hold anything that can be
used to recover the 'password' and a reusable challenge never
goes across the network, so getting a copy of the authentication
conversation does an attacker no good.
(If an attacker can use a public key to recover the secret key, everyone has some bad problems.)
- Use some sort of challenge-response system that doesn't expose the
password in plaintext or provide a reusable challenge, and that
allows the server side to store the password in a form that can't
be readily attacked with things like off the shelf rainbow
tables. You're still vulnerable to
a dedicated attacker who reads out the server's stored authentication
information and then builds a custom setup to brute force it, but
at least you don't fall easily.
(OPAQUE may be what you'd want for this, assuming you were willing to implement an IETF draft. But I haven't looked at it in detail.)
As far as the practical answers for IMAP, authenticated SMTP, and so on go, I have no idea. For various reasons I haven't looked at alternative authentication methods that IMAP supports, and as far as websites go to do anything other than plaintext passwords that get passed to you over HTTPS, you'd have to implement some security sensitive custom stuff (which has been done by people who had a big enough problem).