220

Our client has come up with the requirement that in case the username in question has had multiple failed login attempts, the incorrectly entered password(s) must be shown once a successful login is performed. Correctly entered information, including previous passwords, will not be shown in any case.

Our lead dev has told us it is technically possible by not hashing incorrect entries, but she is extremely uncomfortable with the feature and thus it has been put on hold while we brainstorm it out.

The website in question is a broad mapping/GIS application that does not feature any monetary transactions whatsoever. Other login/authentication options include Google/LinkedIn/Twitter/facebook, so obviously no passwords to be stored there and handling that is primarily a UX issue.

What security vulnerabilities come with implementing such a feature? Our client is not entirely without technical knowledge so a general explanation is enough.

My apologies if the question is too broad or the answer very obvious.

  • 140
    Ask the client why. Then ask why about whatever they say. They may have an idea, but surely they don't want to do this. – user123931 Sep 9 '16 at 19:10
  • 80
    enormous legal liability - do not implement unless you have the client remove all legal obligations on your company's part – timpone Sep 9 '16 at 21:44
  • 23
    What @timpone says. Because, as anyone in infosec perfectly well knows, humans often have 100 accounts (I have 154) and no human can remember all that, reuse happens. Even if your site has little to lose, and even if the user shares its password with other sites with little to lose (eg FooFlix, what's he gonna do, steream some movies?) imagine his surprise when a hacker finds a way (e.g. buying thousands of dollars of gift memberships). – Harper - Reinstate Monica Sep 9 '16 at 22:30
  • 18
    (Convince your client and) just go with the standard screensaver info: "The had been X unsuccessful login attempts". – grochmal Sep 10 '16 at 0:07
  • 18
    High five to the lead dev who expressed discomfort and provoked this issue! – Ben Mosher Sep 13 '16 at 11:53

13 Answers 13

355

The primary issue is that incorrect passwords have to be stored in a way that allows them to be later displayed to users. Which, as your dev pointed out, means they can't be cryptographically hashed first. The result is that you store them either as plaintext (bad) or encrypted (better but not normally recommended).

The biggest risk is if this database of invalid passwords becomes accessible to attackers. Either they compromise the server, perform SQL injection, or retrieve it in some other way. Rather than cracking the primary passwords, which hopefully are strongly hashed and therefore tougher targets, they could decide to compromise accounts using the information in the invalid password history. Either they access the plaintext passwords easily, or they attempt to find the encryption key that allows them to decrypt back to plaintext passwords.

A common source of login failures is minor typos during the password entry process. So my password is Muffins16 but I type in mUFFINS16 because my caps lock is on. Or Muffins166 because I hit the same key twice. Or Muffina16 because my finger hit the wrong key. As you can see these variations are close enough to the original that attackers can probably determine the valid password from invalid passwords by trying a few minor alterations or comparing wrong passwords to likely dictionary words or names.

This problem is exacerbated because most people use password choices similar to these formats and not random strings. It is harder for an attacker to identify the typo if your invalid password is V8Az$p4/fA, although still much easier to try variations of that then guessing it without any info.

Another risk is that users may not remember which of their passwords they used on this site so they try their common ones. Now this site is suddently a bigger target because an attacker might be able to not only compromise a user's account there but also on other sites with the handy list of 'invalid' passwords.

You can mitigate some of these risks by wiping storage of invalid passwords immediately after display following a valid login. That should limit the window of opportunity for an attacker to access and benefit from the data.

The question you should probably ask your client is how they predict users will benefit from seeing their invalid passwords. Is it so users can identify how they mistyped their password? Typos aren't intentional so it's not likely that showing them their mistake will improve future login attempts. So users can identify an attacker trying to guess their passwords? Similar feedback can be provided by listing date, time, IP/geolocation or other info for invalid attempts without the attempted password. So users know that they screwed up during password entry and don't blame the site's login system? This seems like the only one with merit and I'm not sure it provides enough value to justify the risk.

My guess is that once you better understand what they're trying to accomplish with this feature you can probably suggest more secure alternatives.

  • 90
    What's your email so I can try the password Muffins16 on it? I mean, discuss this important topic with you further? – corsiKa Sep 9 '16 at 22:49
  • 106
    Obviously that's a trick, the real password is mUFFINS16. – Steve Jessop Sep 10 '16 at 10:09
  • 20
    Cracking the database would be extremely easy—just try 1000 incorrect password attempts on several dozen accounts before stealing the encrypted database. Voila, you now have several thousand "known plaintext" wrong passwords in the database from which you can work out the encryption key. – Wildcard Sep 10 '16 at 18:36
  • 49
    @Wildcard um, what? Why would known plaintext help crack the key of a modern crypto algorithm? – Ben Sep 10 '16 at 19:56
  • 22
    @vlaz the point is that modern crypto is not vulnerable to a known-plaintext attack so having any number of known plaintexts will not help you crack the encrypted passwords. – Boris the Spider Sep 11 '16 at 9:47
198

tldr; this is even worse than not hashing your passwords and storing them as plain text.

I agree with your lead dev's concerns. In order to show past incorrect password attempts, you must store them in a reversible fashion, which means they cannot be hashed. If someone compromised the system, they would then have access to all the bad attempts, and likely could piece together what the true passwords are for some users. For example, if you can see some of my bad attempts were:

correct horrse battery staple
correct horse batttery staple

It would be pretty easy to figure out my actual password.

I also agree with drewbenn's answer: if I type in my username incorrectly but with my correct password, and the incorrect username happens to be someone else's username, now that user can see my real password.

  • 119
    Another vulnerability: once you successfully log in, anyone who's also looking at your screen can see the bad attempts without even having to gain access to the database. – Milo P Sep 9 '16 at 22:00
  • 5
    Also, you can't discard the correct (horse battery staple) password once it's been hashed; you have to wait until after it's been checked to know whether to keep or purge it. – Ghillie Dhu Sep 10 '16 at 1:10
  • 9
    @GhillieDhu That's a very short time window and the password would only be in RAM. (And the password was already in RAM so you could hash it, keeping it there for a few milliseconds more won't do anything significant) – user253751 Sep 12 '16 at 7:21
  • 18
    The bottom paragraph of this answer is pretty much the most damning of examples showing that this should NEVER be done. – thomasrutter Sep 13 '16 at 4:39
  • Shouldn't it say tsdr;? – NuWin Sep 14 '16 at 17:59
94

Once I tried to log into a system using my password but my coworker's username.

Then there are all the times I used the wrong password when trying to log into a shared account.

And I know a lot of admins are granted access to their boss' account so they can get things done. I'd be pretty shocked if their bosses had never entered the wrong password then gotten distracted by a visitor before logging in correctly to clear the mistake.

Plus all the typos when someone's standing over my shoulder while I'm logging in.

And in all of those cases, sometimes I've entered my gmail or lastpass password into the password prompt at work, and vice versa.

And the time I googled my password because I wasn't looking at the screen and just assumed it was locked. Not that that has anything to do with your proposal, but I like sharing that anecdote because it reminds people that everyone can make a mistakes and type in the wrong thing sometimes.

The only thing this hUnt3r2feature does is turn small mistakes (entering in the wrong password or mistyping it) into accidental exposures to a wider audience.

  • 46
    If I want to crack your account drewbenn all I have to do is set up a few common types of your username: drewben/derwbenn/... and wait until you misstype your username and send me your password :-o – Falco Sep 12 '16 at 7:51
  • 10
    @Falco you should add that as an answer. That's a good way to actively attack users on a system like this (and something that would be invisible to the target, assuming the common (and good) security measure where "wrong password" returns the same error code as "invalid user"). – user15392 Sep 12 '16 at 20:51
44

Reputational loss

Putting such a mechanism in place would result in immediate reputational loss, considering there have been high profile cases where failed login attempts have been used to attack other sites. Here is an example:

Mark (Zuckerberg) used his site, TheFacebook.com, to look up members of the site who identified themselves as members of the Crimson. Then he examined a log of failed logins to see if any of the Crimson members had ever entered an incorrect password into TheFacebook.com. If the cases in which they had entered failed logins, Mark tried to use them to access the Crimson members' Harvard email accounts. He successfully accessed two of them.

In other words, Mark appears to have used private login data from TheFacebook to hack into the separate email accounts of some TheFacebook users.

Source: How Mark Zuckerberg hacked into the Harvard Crimson

An alternative

If your client is hell bent on showing failed login attempts upon next successful signon, as sort of a feel-good measure, may I suggest an alternative? Instead of displaying the failed passwords, display the IP address and geolocation information of the browser which submitted the bad password. Should be fairly easy to do, would not cause a security issue, and would be providing much more useful information in case of actual malicious activity.

  • Nice alternative! It might be extended to also include statistical information about how close the failing passwords were to the real one, like "4% difference". So the user can even better judge what were her own failed login attempts and what were hacking attempts. Difficult to implement though, as we can safely only access either a failed password or the real password in cleartext (on login before hashing) and can't store them. Perhaps possible with functional encryption? – tanius Sep 9 '16 at 22:50
  • 35
    @tanius no, the site should not be able to calculate that difference! – guntbert Sep 11 '16 at 14:01
  • 5
    Your mentioned alternative is what happens at Steam when your account has been compromised but the attacker has no access to your 2nd authorisation factor. You'll be shown which device is trying to gain access so you can verify whether you screwed something up or you're under attack. It works pretty well and is a heck of a lot better than what OP's client proposed. – Mast Sep 11 '16 at 16:34
  • 2
    @guntbert, at the time when the incorrect passwords would be shown, the correct password is available for comparison even if properly hashed, because the user just entered it. – Ben Sep 12 '16 at 12:38
  • 3
    @Ben Right, but storing the incorrect passwords is the problem (no hashing possible). – maaartinus Sep 12 '16 at 13:49
39

A non-security reason not to do this: Bad login spam.

I run my list of emails/usernames against your application. I attempt to login to each account with the same 'password'. Maybe an offensive phrase; political slogan, or simply an ad for some website.

Then each of your users logs in, those with the usernames/emails I guessed are forced to look at whatever I entered.

It gives every single anonymous person a vector for displaying content to your users.

In the case of coworkers that each use the service and who can likely guess each other's login names this might even result in harassment or other workplace HR issues.

  • 4
    This is a very important issue that I think has not received enough attention. – Alejandro Piad Sep 16 '16 at 18:22
  • 3
    I had not thought about this before, but it is actually a security issue. – emory Sep 19 '16 at 17:31
23

What happens when I want to login to your app and I am sitting with my coworker? Suppose I mistype my password. Do I now need to send him away while I login so that he doesn't see my password attempt?

  • 6
    "What happens when I want to login to your app and I am sitting with my coworker?" -- I know someone whose entire lab, as PhD students, trained themselves to read each other's passwords by watching each other type them. Helps to see it several times, apparently. Must have been a laugh a minute down there, and if you do this you take all the fun out of it. Security rule number one: don't be a killjoy, keep it challenging for the attackers. – Steve Jessop Sep 10 '16 at 10:13
17

If there are users with similar usernames/email addresses they may accidentally attempt to log into another user's account.

A malicious user could then use their list of "incorrect" password attempts to break into accounts with similar usernames/email addresses (e.g. bill11, bill1, etc.).

I think it would be better to simply list bad and successful login attempts along with the time and relevant IP address.

  • 6
    This, to me, seems a far greater risk than the accepted "what if the DB gets into the wrong hands" risk. There are any number of systems where I try to register, find my preferred username is taken, and cycle through others. After some time, I have forgotten which I used for a particular site, so I must cycle through them when trying to login after an absence. But my password is always calculated from sitename plus year plus other details, so is unchanging. So while the DB MAY fall into the wrong hands, there WILL be users who see other people's correct passwords. – Dewi Morgan Sep 12 '16 at 4:44
11

I agree with other answers pointing out that it makes it easy to guess a user's password if an attacker got a hold of the list of failed attempts.

That being the case, it does not matter that your system does not contain any monetary transaction information. It is common for users to use the same password, or variations on the same password, across multiple sites. They may be advised not to do it, but it still happens. So just because you don't feel your system exposes sensitive information itself does not mean your users' sensitive information is not put at risk if your system is compromised.

If Joe User uses the same password on your system as he uses for his bank, if an attacker were able to guess his password on your system and figured out what bank Joe used, the attacker could get access to Joe's bank account. Or medical records, or any other system Joe used that password on.

You aren't just protecting the passwords for your system.

  • 5
    And if I type in my top secret banking password by mistake for your system, it will also be remembered. – gnasher729 Sep 10 '16 at 15:24
9

I suspect that your client is suffering from an XY problem. This means take a step back and try to figure out what your client really wants. Often it's useful to know that someone tried an incorrect password and how this password was entered, not necessarily what that password was. Perhaps the client just wants enough information to distinguish benign threats, such as fat-fingering your own password, from more suspicious ones, such as guessing passwords from halfway across the country on a device that has never logged in before.

So ask your client about the threat model and see if the following information is enough:

  • user ID for which authentication failed (so that you can know whom to warn for each failure)
  • date and time
  • client IP address, user agent, and approximate geolocation
  • whether the client runs JavaScript (attackers often don't bother)
  • whether the client presented a cookie for having logged in successfully in the past

Then present a warning box based on this information when a user successfully logs in after one or more failures.

  • A warning box might not be sufficient if there have been multiple attempts. Also, the user should be able to come back to the list if desired – pppp Sep 13 '16 at 19:27
  • 2
    The best reason by far not to show the old paswords is indeed that there is no need to do something this tricky. -- My first thought on why people would want this, is that they don't believe they have fat fingers, in which case you could simply use something like 'hit insert to show the password' as is implemented in major software solutions. – Dennis Jaheruddin Sep 14 '16 at 14:02
7

I hesitate to add to the already excellent answers here, but there is another important point. Unless you are absolutely certain that users only connect to the site via HTTPS (and truthfully, not even then) you should never even have the opportunity to display the incorrect passwords... as they should never be transmitted (encrypted or not) in the first place. Client systems should only transmit something like a salted hash, not the actual password (in a proper implementation, to ensure that the hash itself does not become the password, i.e., something that can be stolen and reused), to prevent eavesdropping attacks.

And it doesn't matter that the site is not processing financial transactions. You still do not want it to become the weakest link in some chain.

So I am fully with your lead dev on this one. I would be fighting tooth and nail against this "feature".

  • So that the server would have to store, what, the salted hash generated by the client? How is this functionally different from just sending the password over a secure channel and letting the server hash it using a real password digest algorithm like pbkdf2, bcrypt or scrypt, none of which are implemented in web browsers (a) and (b) if the client sends a hash, all it is doing is proving that it knows the hash, not that it knows the actual password, which is ultimately less secure than sending the password and doing real cryptography on the server. – Craig Sep 20 '16 at 8:15
  • There are bscrypt/scrypt implementations in JavaScript. And double hashing can ensure that what the client sends does not become the password (cannot be reused). My concern with any implementation would be the manner in which a non-predictable salt for the second hash is created, stored, and sent to the client. – Viktor Toth Sep 20 '16 at 14:48
  • If the server is sending JavaScript to the client to hash the password, you're still extending the same level of trust to the owner of the server, plus you're providing an opportunity for a man in the middle to send you an altered script, plus removing the ability for the server to easily version, upgrade and control the cryptographic protocol in use, plus exposing to any would-be attacker exactly which protocol you're using and how many rounds, etc. I still see more problems than benefits, respectfully. – Craig Sep 20 '16 at 15:23
  • 1
    Essentially, but that's only one of my points. That secure channel is HTTPS with forward secrecy and already exists. If a server is sending you a script to process your password, the server may as well just process your password presuming the channel is secure. There is no net gain from hashing on the client, yet there are plenty of potential issues with hashing on the client. – Craig Sep 20 '16 at 15:32
  • 1
    We've been getting the "chat" warning. But what you're suggesting requires that the server pass both salts to the client, because the client certainly can't be counted on to remember the original salt. When the password hash was originally stored on the server, the plaintext password had to be passed to the server, or the original salted hash had to be sent, and it was interceptable. And as I mentioned previously this makes things like versioning the password hashing algorithm more difficult and error-prone. I just see a ton of holes in this. ;-) – Craig Sep 20 '16 at 21:15
7

A possible solution: Since the concern here is about storing incorrect password attempts in plaintext, avoid it. When a user's password is set, generate a public key and private key pair. Store the public key and private key encrypted with the password. When logging incorrect passwords, encrypt them with the public key (and add salt). This way, only the user who knows the correct password can see the incorrect passwords.

  • 3
    This does seem like a viable solution to the major concern. It still doesn't address seeing other people's password due to accidental login with your username. And of course the solution fails when you change your password. But good idea. +1 from me. – TTT Sep 10 '16 at 15:04
  • 6
    This does not prevent against attacks which rely on the username being mistyped. – Michael Sep 12 '16 at 21:15
  • Among all the other reasons I think this is a bad idea, encrypting and decrypting data with asymmetrical keys is literally orders of magnitude slower than symmetrical encryption. The extra load on your servers would be nothing short of ridiculous. – Craig Sep 20 '16 at 8:05
  • @Craig Doesn't SSL require about the same load if not more than encrypting with an asymmetrical cipher? – v7d8dpo4 Sep 20 '16 at 12:58
  • SSL uses asymmetrical encryption to securely generate and share a symmetrical encryption key, which is then used to encrypt all of the data in transit. – Craig Sep 20 '16 at 14:09
4

Your system will have a large decryptable database of passwords. Looking up the incorrect passwords for user X, you will get almost but not quite correct passwords for X's account, correct passwords for different accounts of the user X, plus correct passwords for accounts of users with almost the same username as X.

With the reasonable assumption that a hacker could break into your system and get a decrypted copy of the database, this would be desastrous. Even assuming that access to your system by the wrong person isn't too critical, that database will contain passwords of your users for different systems which might be much more critical.

0

It seems to me that in a properly constructed authentication, the password the user typed is not even transmitted to the host site, so the question of storing incorrect attempts is moot.

It might be acceptable to have a "see password" checkbox in the interface, which is strictly a local function, and could be used either as the password is being typed or after a failed attempt. Probably the saved information should be wiped after a short time to prevent harvesting passwords from abandoned consoles.

  • 5
    Huh? The password you enter on a website is always transmitted to the host server in order to be verified. Can't trust the client to authenticate itself against itself, and client-side hashing/obfuscation is pretty pointless. The password is hopefully transmitted using SSL/TLS, so it's encrypted in transit, but it is sent to the server regardless. – Flambino Sep 15 '16 at 21:23
  • No, some variation of; the server gives you a random string, you hash the password with the random string and pass it back to the server, server compares what you sent with the expected result, proving you know the password. – ddyer Sep 16 '16 at 4:51
  • 2
    And proving that the server stores all passwords in plaintext. Otherwise it can't do the hashing. So that's a much worse solution. – Flambino Sep 16 '16 at 6:46
  • Not necessarily, it depends on the exact hashing protocol. For example, hash the password with a known, fixed method, which theoretically reproduces what the server stores. Then hash the result with the newly presented random (avoiding replay attacks). – ddyer Sep 16 '16 at 15:14
  • 1
    @ddyer how are you proposing that the server knows the expected result, unless the server is hashing the password using the same algorithm in order to perform the comparison? A well vetted handshake to establish a secure channel is what HTTPS is all about. Roll-your-own encryption is tough to do right. – Craig Sep 20 '16 at 20:44

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