43

On Code Review stack exchange, in response to code that informs the user when their login attempt failed because of too many login attempts from an IP, I was told

"Absolutely do not message end user telling them why login failed. You are giving a potential attacker critical information to aid them in attacking you application. Here you give an attacker very precise information to get around your IP restriction."

https://codereview.stackexchange.com/a/164608/93616

Am I practicing bad security? Should I explain in more vague terms like "Too many login attempts" or "You could not be logged in"?

Update: In case there's any ambiguity, currently the too many attempts logic and message does not care if the attempts were successful or not.

Goose
  • 1,394
  • 1
  • 11
  • 17
  • 61
    The "absolutely do not" is far too strong. Security is a trade-off with usability. As a counter argument, Google will happily tell you when too many suspicious queries have been made by your IP address, and I've found that a very useful bit of information in many cases. If Google can do it, so can you if you feel it will help your users more than attackers. If not, don't. – Xander May 31 '17 at 16:55
  • 17
    "Absolutely do not message end user telling them why login failed." - I think this statement is more aimed at not returning information such as "This account does not exist in the system". An attacker can use the various responses to the login requests to determine if a specific user account exists in the system. In other words, the logon response should be the same whether or not the account exists and/or supplied password is incorrect. – SecretSasquatch May 31 '17 at 17:51
  • 1
    I would use an anonymizing proxy to get a new IP address every request, so what's the point of blocking by IP? You should block by incorrect authentication by username – Neil McGuigan May 31 '17 at 18:25
  • 3
    @NeilMcGuigan That only blocks attacks in a single dimension. It doesn't block against a bot trying a common password across thousands of usernames. – Xander May 31 '17 at 19:26
  • @Xander correct. You can also block on failed passwords – Neil McGuigan May 31 '17 at 19:48
  • 1
    @NeilMcGuigan No, not in the same way, for several reasons. – Xander May 31 '17 at 20:22
  • 1
    an attacker can figure this out pretty quickly anyway, it's not a huge secret... – dandavis Jun 01 '17 at 03:00
  • @schroeder Since I can't comment on my deleted answer to make my case, I'll make it here. Apologies that I didn't do well enough at putting my answer across clearly. It was definitely intended to answer the question. I was giving some concrete examples of where false positives might occur, which other answers haven't yet done, to make it clear how common it would likely be. I was then linking this with the final sentence of the answer back to the question - if you deny login attempts without explanation from blocked IPs, all these false positives are going to wonder what's going on. – Muzer Jun 01 '17 at 09:53

5 Answers5

79

Absolutely do not message end user telling them why login failed. You are giving a potential attacker critical information to aid them in attacking you application.

On the other hand, not telling a user why their login failed is a potential usability disaster.

If you don't clarify whether the user's IP was banned or the user instead used a wrong password, they might panic since it seems to them that someone accessed their account and changed the password to lock them out. If my login with a pre-filled password fails, the first thing I'm thinking of is a break-in rather than an IP block.

Also, a naive IP blocking mechanism might be ineffective and introduce additional problems. It is potentially trivial to bypass for an attacker with sufficient resources and someone who shares an IP address with other users might abuse the IP ban to lock out others. Instead, a CAPTCHA after n failed attempts per IP might be a softer solution and more appropriate for your application.

Also see:

Arminius
  • 43,922
  • 13
  • 140
  • 136
15

There is a security benefit to providing generic messages that hasn't been mentioned.

Alice is attempting to brute force an account on Bob's server. For the first few attempts Alice gets back the message, "Failed login attempt". On the next attempt she gets "Too many login attempts from this IP address". She's now aware that (a) all the credentials she tried up until this point were invalid, and (b) she needs to do something different before making more attempts.

But what about if Bob doesn't change the message? Alice will continue with the brute force and will continue to get the generic "Failed login attempt" on each attempt even if the credentials are correct. If she does happen to try the correct credentials, Bob will reject the attempt because the IP limit has been exceeded, but Alice won't know that that is the reason and will have to treat it as an incorrect attempt (unless she has some other way of knowing which is beyond the scope of this question). Her only option is to continue with the search, unaware of whether or not she has already located and moved past the correct credentials.

Note that this benefit is security through obscurity since it relies on Alice not knowing Bob's IP blocking policy. Depending on the setup, this information might be trivial to obtain. For example, if Alice has access to another account on the system (easy if it accepts public account registration) then she can use trial and error to see if a correct attempt eventually gets rejected after too many incorrect attempts.

Other answers have explained the security vs usability trade-off, so I won't bother repeating that.

Jon Bentley
  • 2,001
  • 2
  • 14
  • 16
  • 1
    Note that Alice cannot verify accurately the correct password unless password checking, with the return message, happens before "too many attempts" checks. The reverse ordering gives less information, only allowing Alice to distinguish "incorrect" passwords from "unknown" passwords. Which is still may be an undesirable amount of information to give to an attacker. – godskook May 31 '17 at 18:12
  • This answer presumes "incorrect password" but the "failed login" message really only means "incorrect username, or incorrect password for that username". (There might be a side-channel attack if the incorrect username is rejected earlier, but it's well-known to randomize the wait time for a failed login message) – MSalters Jun 01 '17 at 08:49
  • @MSalters True, but it doesn't affect my answer. Either way, the effect on a brute force attacker is the same: with a generic message they can't tell the difference between correct and incorrect credentials and have to treat them both the same. The differences between a "Incorrect password" and a "Failed login" message is a separate security vs usability issue. I'll edit my answer to make it clearer. – Jon Bentley Jun 01 '17 at 09:45
13

Yes, technically you are returning information which could be used by an attacker to fine tune a brute force botnet. In addition, I'm not sure how useful the "To many login attempts from this IP" error message will be to a standard user. It should also be noted, that any seasoned attacker will start to notice either a changing response type, or a timing difference, and will probably figure out what is happening, anyway.

You may want to consider using a service such as CloudFlare. They have a scriptable API which can dynamically insert an interstitial page or update a WAF rule under certain scenarios. Troy Hunt has a good tutorial where he does this for Windows Azure using Azure Functions.

Dan Landberg
  • 3,312
  • 12
  • 17
  • 1
    This answer makes sense. What should I tell the user when they hit the limit? I'd like to avoid getting CloudFlare involved at this point. – Goose May 31 '17 at 16:53
  • 5
    The recommendation also comes from developers not always being consistent with the errors they show. You need to be careful about that as well. For example if I am attempting to brute force a user's password and I get "Incorrect log in information" messages, but then I get "Too many attempts from this IP" error. I will know I hit the jackpot with the password even if I didn't log in. – Kotzu May 31 '17 at 17:05
  • 1
    Much of your wording it is going to depend on the sophistication of your users. Something along the lines of "Unable to log in right now. Please try your request again later." If you want it to be the most secure, you would want to avoid listing a specific time limit, since an attacker would just restart his or her attempts after that time limit. Honestly, a smart attacker is going to figure what is happening. I really would recommend using a 3rd party service for this one. You can spend a huge amount of time coding a fix for this, and an attacker will find a way to game the system. – Dan Landberg May 31 '17 at 17:06
  • 14
    @kotzu I don't follow your logic. "Too many attempts from this IP" means too many *wrong* attempts, not "You had some wrong attempts followed by a correct attempt, but we're going to block you because the correct attempt put you over the limit". – Jon Bentley May 31 '17 at 17:15
  • 2
    @Jon Bentley - Yes, that is exactly my point. what you say would be the right way to show the message. But at times I have seen application with a flawed logic that allow the attacker to know when they have hit the right password by being inconsistent with the error messages. – Kotzu May 31 '17 at 17:27
  • 2
    @JonBentley But make sure not to test only wrong attempts either... Otherwise, your brute-force attacker gets a rate-limit error, a rate-limit error, a rate-limit error, then a successful login, and no security is gained whatsoever. – user253751 Jun 01 '17 at 08:38
  • 1
    Cloudflare means​ goodbye security. it's basically *MitM as a Service.* – Display Name Jun 02 '17 at 04:43
  • @SargeBorsch It really depends on your threat model. If you're trying to defend against Nation State attackers, yes, it probably makes you weaker. For most applications, it provides a significant improvement in security in terms of DDoS prevention, WAF, and other features. – Dan Landberg Jun 02 '17 at 13:52
  • @user52472 Cloudflare is danger anyway, because they have also demonstrated their incompetence. (see Cloudbleed hole) – Display Name Jun 02 '17 at 13:59
6

In this case, security and usability are contrary goals. While the most secure implementation would offer no feedback, it would also be least user-friendly. You need to decide how susceptible your system to brutforcing of logins, what other mitigations are in place, and how effective specific mitigation is when evaluated against inconveniencing the user.

For example, if I were designing login for a consumer device I would make it as user-friendly as possible by having detailed feedback and introduced additional mitigations to compensate. If I were designing HSM login, then I would offer no feedback and onerous device-wide timeouts.

Kirill Sinitski
  • 989
  • 6
  • 12
2

All depends on what you are building. If it is a blog or any other fancy site where it is not really important to reject legitimate attempts, and where you do not really trust the robustness of the application, you really should protect it from anything that could be an attack and never tell why you reject a login.

If you are building a professional application and expect professional accesses do not limit accesses from a single IP if your application is robust enough. If you do, be sure to inform the user of the reason, and set up a reasonably responsive hot line (at most 1 working day to read and understand a message, and to initiate a corrective action if needed). Because it is common for large organizations to setup a single outgoing proxy for all their HTTP and HTTPS accesses. You may have thousands of employees in different locations in a country, all using apparently same IP address. A white list allowing unlimited connections from known proxies is enough, but you must be ready to change it quickly if one of your customers makes his network evolve and changes his proxy address.

Serge Ballesta
  • 25,636
  • 4
  • 42
  • 84