38

I started logging failed logins attempts on my website with a message like

Failed login attempt by qntmfred

I've noticed some of these logs look like

Failed login attempt by qntmfredmypassword

I'm guessing some people had a failed login because they typed their username and their password in the username field. Passwords are hashed in the database, but if somehow the db got compromised, these log messages could be a way for an attacker to figure out passwords for whatever small percentage of people end up having a failed login such as this.

Is there a better way to handle this? Should I even worry about this possibility?

65

Try it like this:

If the username exists, log "failed login attempt by username". If not, log "failed login attempt by IP 123.45.67.89" instead. That should take care of the problem of having passwords show up in the log accidentally.

  • 13
    You could also check for an empty password and fail with an appropriate error in that case. – Mike Weller Apr 22 '13 at 5:52
  • Printing the username is the problem the OP was describing. Sometimes a failed login is caused by the user missing the [tab] key and quickly typing both the username and password into the username field and hitting enter. Your suggestion does not handle this. – BZink Apr 24 '13 at 18:17
  • 7
    @BZink: Yes it does. If the username exists, log it as such. If what the user does is accidentally add the password onto the username, the resulting string will almost certainly not also be a valid username. – Mason Wheeler Apr 24 '13 at 21:00
12

Why not to simply check if such username exists in database? This will leave you with 2 possible outcomes.

  1. User entered a correct username. You then can simply log what you log now.

  2. User entered his password in in username field, therefore username is invalid. Just enter a log entry saying that there was failed log in attempt by unidentified user?

And of course you can have an extra field to log ip, date and what not?

  • 3
    Why not append a hash of the username to the log entry in #2. This will hide the password, but at the same time allow someone looking at the logs to determine if there are multiple attempts by the same unidentified user. – emory Apr 22 '13 at 12:39
  • If there isn't a record containing the username, it's obvious they got it wrong, so this is still useful for trouble-shooting. – JeffO Apr 22 '13 at 12:42
  • 2
    @emory, if user mistakenly typed in they're password together with username there is no viable way to extract just the username part of the string. And someone repeatedly entering they're password to username field is very unlikely I think. This is a "once off" mistake that you do. Happens to the best of us, but I doubt there is anyone stupid enough to keep doing it without realizing it :D – galdikas Apr 22 '13 at 14:34
  • @galdikas There is no need to extract anything from the user name. For example, I am user 'user' with password 'password'. I login with 'userpassword' and your hash function maps 'userpassword' to 17. The logs will say "Failed login attempt by unidentified user 17". – emory Apr 22 '13 at 14:43
  • 1
    @galdikas There probably is not anyone stupid or persistent enough to keep doing it more than a few times, but there are scripts that are stupid and persistent enough to do it thousands of times. Wouldn't you like to know the difference? – emory Apr 22 '13 at 14:44
1

Considerations:

  1. Can you detect when this has occurred, as opposed to someone mistyping their username? Logging mistyped usernames can be useful for support purposes, i.e. answering the question "why can't I log on" with the answer "You have mistyped your username, that should be a dash not a dot", or "You have a leading colon then whitespace - have you cut and pasted it". If you have a small number of high-value paying users (i.e. not yet another social networking site) then you will probably have to supply this kind of support.

  2. What is the appropriate action should someone do this? Usernames may be indicators of hacking attempts. The fact that the username doesn't appear in your list doesn't mean you don't need to know what it was. However if you believe this is a serious concern, and you could detect whose password it was, you could require the user to change their password after this has occurred.

  3. What is industry practice? Industry practice is to log the username field but not the password field. You are unlikely to get fired for doing this.

Unless you have out-of-the-ordinary considerations, I would suggest following industry practice, and log the username field, regardless. Consider forced password changes as suggestion 2 if you think this is inadequate.

1

Just to be safe, the logging in my current app does not store parameters passed to login or password-reset methods. The log call has an optional parameter that controls this, which, when set to true, replaces the stored parameters object with [Redacted]. Sure, so I miss out on a little data, but I have their IP addresses, and I'd rather not risk getting something that sensitive in plaintext.

If you really want to log this kind of thing, I'd suggest that when logging a login attempt, you check the database for users with a name matching what you have in the username field, and only store it if you have a match. Otherwise, you just store it as "unknown user". You could get fancy, checking if this value contains that or whatever, but there's always the risk that you get combinations like [User][Password] and [UserPas][sword], in which case you can check against the IP and deduce that you've inadvertently stored the start of someone's password in the clear. You could extend this to the unlikely-but-possible [User][Password] and [UserPassword][??], in which case you can see "unsuccessful login by UserPassword" followed by "Successful login by User" and deduce all of User's password. Generally, to be safe I'd say to not log usernames unless the login is successful.

Edit to add:

Most of the arguments people are posting for logging the username for failed login attempts are, in my opinion, better handled through other methods.

For example, it's been said that when a customer asks "why can't I log on?", logged usernames would allow you to point out typos. This is true, but it's not worth the risk of also catching passwords; I'd do this by instead redirecting the user back to the login form on failure, highlighting the username field and repopulating it with whatever they typed so that they can see for themselves.

Another argument was that it lets you identify hacking attempts; a string of failures against one username may well be an attempt to brute-force a password. I'd do this by having a "BadLogins" column on the Users table, which is incremented each time a login fails with a username matching this user, and is reset to zero on a successful login, after telling the user "there have been x unsuccessful login attempts since your last login" and advising them on what to do if they don't think the attempts were from them. If you want to be really thorough, you could have another column that stores the last value of the BadLogins column even after the successful login, and/or a column that stores the highest-ever value of this column, and/or a column that stores the total number of failed logins this account has ever had.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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