106

How secure is sending passwords through email to a user, since email isn't secured by HTTPS.

What is the best way to secure it? Should i use encryption?

user310291
  • 1,413
  • 2
  • 12
  • 13
  • 66
    No, no, no, no no! Never ever use plain text passwords in email. Infact never send passwords at all if at all possible. – ewanm89 Aug 01 '12 at 13:19
  • 9
    Worth reading this blog post by Troy Hunt on Tesco, the UK's leading supermarket, sending passwords via email. http://www.troyhunt.com/2012/07/lessons-in-website-security-anti.html – Simon Whitaker Aug 01 '12 at 14:05
  • 8
    No, never. We even shame those who do at plaintextoffenders.com. – Omer van Kloeten Aug 01 '12 at 14:43
  • 4
    @SimonWhitaker Amusing that you posted that - I've been heavily involved in the campaign to get them to fix it! :) – Polynomial Aug 01 '12 at 15:30
  • 12
    The fact that you can send users their password means you're storing user's password in plain text or at least a reversible cipher. That alone is a cause for red flag. – Lie Ryan Aug 01 '12 at 15:52
  • @user606723 How do all the banks manage to ask for x, y and z letters from passwords if they aren't doing some strange stuff with them or not encrypting them at all. Certainly not hash of salt+pass... – ewanm89 Aug 01 '12 at 17:37
  • 2
    @ewanm89: banks are the primary offenders when it comes to security. That said, it's possible the question is implying sending a temporary password to the user as a recovery measure. Lots of sites do this, then force you to change it as soon as you login. – Wug Aug 01 '12 at 19:43
  • 1
    @ewanm89 banks could in theory at least be storing hashes of every combination of characters they're going to ask for. – Flexo Aug 02 '12 at 08:22
  • In addition to what others have said, do note that e-mail can be encrypted on the wire (HTTPS isn't the only encrypted protocol in common use out there!). My own mail server is set up to do opportunistic `STARTTLS` encryption over SMTP, and the POP server won't even let you log in unless you start a TLS session first. That doesn't address storage, though. – user Aug 02 '12 at 08:24
  • @ewanm89 Actually, the "secret word" challenges like that are usually implemented in a black-box HSM, so you'd have to physically compromise the device to break them. – Polynomial Aug 02 '12 at 09:49
  • @MichaelKjörling "_My own mail server is set up to do opportunistic STARTTLS encryption over SMTP_" do you check the TLS certificate? Against what? – curiousguy Aug 02 '12 at 16:33
  • @MichaelKjörling and do you require it for all sent and received mail to other servers... What about any server the mail gets relayed through, can you guarantee those? – ewanm89 Aug 02 '12 at 23:51
  • @curiousguy Certificates are checked against the CA certificate set supplied with the operating system's SSL implementation. – user Aug 03 '12 at 07:41
  • @ewanm89 It's set up to do **opportunistic** encryption; not to require TLS. Requiring TLS for simple SMTP traffic to every random server on the Internet would break far too much, but anyone who asks is told that STARTTLS support is available over ESMTP, and it is used occasionally for both incoming and outgoing traffic. And *of course* I cannot guarantee anything about how other mail servers are set up. I can only take responsibility for my little corner of the Internet. If I want end-to-end security, I use GnuPG. – user Aug 03 '12 at 07:44
  • @MichaelKjörling "_If I want end-to-end security, I use GnuPG._" PGP/GPG and TLS on SMTP have different scopes and protect different things. Neither is superior, nor a substitute for the other. – curiousguy Aug 03 '12 at 07:56
  • @MichaelKjörling "_Certificates are checked against the CA certificate set supplied with the operating system's SSL implementation._" the certificate must name the domain of the destination email address? – curiousguy Aug 03 '12 at 08:05
  • @curiousguy "*PGP/GPG and TLS on SMTP have different scopes and protect different things.*" That's kind of my point. "*the certificate must name the domain of the destination email address?*" No, because one server with one certificate can potentially handle e-mail for many domains. Even if the server did somehow know which certificate to present, a single SMTP transaction can involve delivery to recipients on different domains on the same server, so it wouldn't have any way of knowing which certificate to present up front. **Anyway** this is going far away from the question as asked. – user Aug 03 '12 at 08:11
  • I once found a webhoster who required a quite secure password... very long (I think at least 12 characters), numbers, special characters and so on... First I thought it was secure. Then they sent it plain text. Never hosted my website there anymore. – Verena Haunschmid Aug 02 '12 at 11:52
  • @LieRyan: What I've seen is the password *reset*, where the system generates a *new* password, mails that to the user, then hashes it and stores the hash in the database. The "email" step is still as insecure as any email, but at least this sequence doesn't require reversible password storage. – Piskvor left the building Aug 07 '12 at 22:34
  • Even if the email was secured by a https connection, it still would not be secure, to send a password. Email is stored in plain text unless its encrypted. This means once the client has downloaded the data its not secure. if we are talking about a web client then in theory the cache is also vulerable, really depends on the client. I won't get into the differences or really the lack of differences between SMTP and HTTP, HTTPS, secured encrypted versions of SMTP. – Ramhound Sep 17 '12 at 14:14

5 Answers5

160

You should never send passwords in the clear, nor should you store them in the clear. You should hash them using a slow one-way cryptographic hash such as bcrypt or PBKDF2. If a user forgets their password, you offer them a "reset password" function, which sends a one-time reset link to their account.

A scheme such as the following is reasonable:

  • Hash all passwords using a salt plus bcrypt / PBKDF2. See my reasoning here. (EDIT, March 2019: use Argon2)
  • Validate the hashes upon login.
  • If a user forgets their password, send them a secure one-time reset link, using a randomly generated reset token stored in the database. The token must be unique and secret, so hash the token in the database and compare it when the link is used.
  • Enforce that a token can only be used to reset the password of the user who requested it.
  • Once the token is used, it must be deleted from the database and must not be allowed to be used again.
  • Have all password-equivilent tokens, including reset tokens, expire after a short time, e.g. 48 hours. This prevents an attacker exploiting unused tokens at a later date.
  • Immediately display a form to allow the user to set a new password. Do not use temporary random generated passwords!
  • Do all of this over SSL.

I highly suggest reading through The Definitive Guide to Forms-Based Website Authentication for a full set of guidelines on how to build secure login systems.

Polynomial
  • 132,208
  • 43
  • 298
  • 379
  • 31
    +1 The root problem has nothing to do with email. The root problem is that passwords are being stored in plaintext or with reversible encryption. Solve that problem and the email question answers itself. – Phil Aug 01 '12 at 14:06
  • 1
    There's nothing wrong with sending a one-time password in the clear. E.g., the system just created/reset an account for you, your initial password is something randomly created (`sA2aXUpHcYrm`), valid for 1 day, and on first login you will be prompted to set your password. You still need to evaluate the security of this functionality as account creation/password reset is often a weak link in your security protocols. – dr jimbob Aug 01 '12 at 17:24
  • 2
    @drjimbob well in effect that just became no different from a reset link, without the autologin and select account part. – ewanm89 Aug 01 '12 at 18:05
  • 1
    "If a user forgets their password, send them a secure one-time reset link, using a randomly generated reset token stored in the database. The token must be unique and secret, so hash the token in the database and compare it when the link is used." This is no different from sending a temporary password. It might even be less secure unless the users browser automatically encrypts HTTP requests (cough internet explorer cough). At least with a temporary password, you can be sure it will be sent over HTTPS, wheras with a token embedded in a GET request, you can't. – Wug Aug 01 '12 at 19:45
  • 2
    @Wug You can't revoke a temporary password as easily, after a set time-frame. It also confuses users, since they'll get a failed login despite the email saying the new password is valid. Furthermore, a reset link forces the user to immediately change their password, which reduces the risk of the temp password being stolen later. I also don't understand your HTTPS argument - why would a link like `https://example.com/reset?token=123...` cause the token to be sent in the clear when logging in? – Polynomial Aug 01 '12 at 19:49
  • The token is part of the HTTP request, not the data payload. If you used POST it would probably be OK, but most email clients won't like that. If you've ever used secure sockets in java, you'd notice that there is a flag which must be explicitly set to encrypt the HTTP arguments, otherwise they will be sent in plaintext even over HTTPS. I don't know if IE behaves this way or not, but knowing its past shortcomings, I wouldn't be willing to make any bets. – Wug Aug 01 '12 at 19:52
  • 3
    @Wug Erm, I think you've misunderstood HTTPS. The entire HTTP conversation, including GET parameters, are all encapsulated inside the SSL stream. Go grab a copy of Wireshark and verify it for yourself. – Polynomial Aug 01 '12 at 19:53
  • Also, it would be easy enough to do, just track both the password hash and a password expiry timestamp in their user info. Send them the password, and store its hash in the database with a 24h expiry time. If they don't use it, password expires and they must request another reset, if they do, it makes them change their password (which also sets the expiry time back to the default of presumably infinity). – Wug Aug 01 '12 at 19:54
  • I'll test when I get home how browsers treat it, but I'm quite sure that parameters may not be encrypted (there was a minecraft exploit some time back that involved sniffing the password out of the session request, which was sent as an HTTPS to a login server which returns a secure session token, but the GET arguments were sent in plaintext). – Wug Aug 01 '12 at 19:57
  • @Wug That's still overcomplicating things. Besides, a completely random token is *stronger* than a password, since it has `2^n` bits of entropy, where `n` is the length of the token in bits. Compare that to a password, which has much harder-to-compute entropy, and sufficed to say that it'll be a lower number. As far as the Minecraft exploit goes, I'm pretty sure that was due to standard session hijacking, i.e. the login screen was HTTPS, but the subsequent requests were plain HTTP, leaking the session ID. – Polynomial Aug 01 '12 at 19:58
  • Why token should be deleted from database after use? Strictly speaking it's enough to just not allow it's use again. – Andrei Botalov Aug 01 '12 at 20:03
  • 2
    The entire request URL is encrypted in HTTPS; this is why secured domains must be hosted on dedicated IP addresses, as certificate selection can't be based upon the request address since that information isn't available to the server until *after* the session has been negotiated. Even so, if the token is one-time-use-only, what would even be the harm in its being sent in plaintext? By the time anyone could have observed it, it won't work anymore. – Adam Robinson Aug 01 '12 at 20:03
  • 1
    @AndreyBotalov What's the point of keeping it in the database if it can't ever be used again? – Polynomial Aug 01 '12 at 20:04
  • 1
    @AndreyBotalov: True enough, deleting it is an implementation detail, but it seems the most practical thing to do (what would be the purpose in keeping it around?) rather than adding logic to determine whether or not the token is valid. – Adam Robinson Aug 01 '12 at 20:04
  • Why hash the token in the DB? What attack does that protect against? – chiborg Aug 02 '12 at 10:57
  • 2
    @chiborg If an attacker breaches the database, he could use the reset tokens to gain access to any account he likes. Hashing the tokens prevents this, since he can't determine what the original token was. – Polynomial Aug 02 '12 at 10:58
  • 2
    I think it's important to state the reason for all of the password-protection mechanisms: It is to protect users' passwords since they commonly use the same password on multiple sites. If your system is compromised it should not compromise the users' passwords. – Sarel Botha Aug 02 '12 at 13:25
  • @SarelBotha Not just that. It's important to prevent the attacker from being able to log into your system using any data he captures from the database. – Polynomial Aug 02 '12 at 13:28
  • 1
    @AdamRobinson Interestingly, we keep the reset tokens, but mark them with a "Claimed" date as it allows us to audit the process after the fact. – Basic Mar 25 '14 at 20:17
  • I know there are some sites that, when you register, it'll generate a random initial password and email it to you, then you log in and it forces you to change it. It doesn't seem as bad (for example, you could send it as soon as you generate it, and never store it as plain-text in your DB), but it's still a bad idea, right? – Kevin Jan 20 '17 at 15:42
  • @Kevin The problem is if the user doesn't log in, you're left with an account using a password that might be known by an attacker. It also becomes a race condition if they're using an untrusted network. If you don't want to ask for a password before verification, there should be a 24h/48h timeout activation link for the account, and then the user should be forced to enter a password for the first time at the point of activation. – Polynomial Jan 20 '17 at 18:48
  • @Phil you don't have to store a password to send it. You can send the password email in the moment it's generated or submitted by the user. And basically it's stored, but it's stored on user side, you don't store the email. – Maciej Krawczyk Jun 20 '17 at 07:50
  • @maciejkrawczyk You can, but you're still then transmitting the password via an insecure protocol (email). – Polynomial Jun 22 '17 at 15:35
43

Email is not secure. Sending a password over email is thus a security risk. To mitigate the risk, you can (in some situations) make it so that the password sent by email is a one-time password, which only unlocks the possibility for the user to select a new password of his own.

This is what good I-forgot-my-password-for-this-Web-site systems do: the user clicks on the button "dammit, I forgot my password", and an email is sent, which contains a URL (with HTTPS) which embeds a random session identifier, and points to a page which lets the user choose a new password. The URL is the "one-time password". With this scheme, you can at least, from the server side, know when the URL was used.

If you can do encryption properly, i.e. if you can send an OpenPGP or S/MIME message encrypted with the user's public key, then the user has a private/public key pair: in that case, why would you use passwords at all ?

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • 9
    So what's stopping the link in the email from being hijacked by a middle-man who uses the link to reset the user's password? – Pacerier Dec 12 '14 at 08:28
  • @Pacerier 2FA (either SMS or, much much better, TOTP) after the recovery token is presented. – Pointy Aug 14 '22 at 17:55
23

It is bad practice to send passwords to the user, as that would mean that you have a cleartext copy of the users password.

I can think of no good reason to do this. There are other more secure ways of accomplishing what is needed.

For a general answer with regards to email security, I suggest you read this link, which has some good information in it.

If you HAVE to send sensitive information over email, use a scheme like PGP or other encryption techniques to secure the data.

  • This is not true; you can create an e-mail to send to the user after the submit to create the password. At a certain point in time, you will always have the password in clear text. While I agree it's not smart to e-mail passwords after creating an account, it doesn't mean the password storage is lacking. You could store the password with PBKDF2 SHA-512 with 10k itterations, this doesn't mean you can't send the password the user picked via e-mail. – NKCSS Aug 01 '12 at 14:12
  • 5
    @NKCSS: one day someone will register an account to your website, using their shared work mail, with their personal password. – Lie Ryan Aug 01 '12 at 16:00
  • 1
    @NKCSS True, you could send the password immediately before storing it, and your *storage* solution could be secure. But sending the password in the clear is still ridiculously insecure. Never minding the possibility Lie Ryan has suggested, you should also be concerned about who could be listening in on the e-mail conversation. The user may be using a service that transfers e-mails in the clear between servers or to the client. See my answer on [this topic](http://security.stackexchange.com/a/13222/953) for more reasons not to trust e-mail for confidentiality. – Iszi Aug 02 '12 at 00:07
4

If you have the 'clear password' to send in the first place (aside from the registration process), you're doing it wrong. Never, ever store the plaintext password! Lots of companies like Sony Music and the like have been being burned lately from that.. and let me tell you the consumers are not happy.

Vaughan Hilts
  • 303
  • 1
  • 8
  • 1
    To be clear (pun not intended), you should *never* send the cleartext password - not even during registration. Yes, by nature of the process, you will probably have a cleartext (or encrypted) copy of the password during registration but it should be immediately salted, hashed, and stored in the *secure* database - never sent or displayed to the user. – Iszi Aug 02 '12 at 00:00
3

Echoing the previous posts, email is certainly not safe and you should never email any sensitive data, in particular passwords. Especially since they are not encrypted and our found in clear text, it is extremely easy for anyone to hack into your email and gain access to these across the public network.

If you or your client have trouble remembering your passwords, you should use a secure password manager. This is a website that houses a list of your passwords in a completely encrypted vault. Good ones are KeePass or LastPass.

If you are a company that is trying to send clients their password again, you should have security questions set up that the customers answer when they initially create their account. This way if they forget it, they can click on a link that sends them to answer these questions correctly and reset their password.

For your own knowledge, this is an informative blog, which makes the case for encryption and warns against using certain passwords http://www.ziptr.com/blog-last-4-digits-ssn-password from Ziptr.

  • FYI: KeePass is not a "website". It's an application. And, by default, it does not synch to the cloud. I believe there are plugins available to synch it with DropBox or other cloud storage services, though. – Iszi Aug 01 '12 at 23:57