At this point, I'm playing devils advocate a bit. I'm not 100% sure I'm sold on this myself, but it's definitely an attempt to deal with a problem I face daily, so I'm continuing this to fully explore the idea.
Also, I am not sure how this will be any greater security risk than the current system of storing a SSHA hash of the current password within LDAP? We could store similar hashes of all the passwords
tried
(upto pwdMaxFailure) and compare against that?
I'm wondering if that's even necessary. According to your description so far, it would be sufficient to only store 1 failed password. If as you say, the same password is tried multiple times, then this should be good
enough.
A brute force attack varies the password. A user having their app save a password and forgetting to change it doesn't - that retries the same password over and over. A brute force attack that uses the same password over and over is pointless, since it will never succeed if it failed the first time, so multiple failed attempts using the same password is not a threat to the password.
The idea of locking an account after too many tries is to prevent a brute force attack and really comes down to a need to stop too many tries with
*different* passwords. Locking a user that has an old password configed in their app that retries that over and over is not really a security issue that we need to stop (you want to stop it for other reasons, but not because it's a security risk). Locking accounts in these cases (same password over and over) is really a negative side effect of attempting to stop brute force attacks that most password policy plugins suffer from.
So the root of the problem is not to stop N failed attempts, per se, but to stop someone trying N or more *different* passwords to break in.
I.e. differentiating between these user cases, which are a problem but are not an "attack", and an actual brute force attack on the users password.
While apps that can save passwords and users that use that feature are questionable from a security POV, it's what we have. Having a way to differentiate and only lock due to the attack case would without a doubt be useful. This isn't "broken" software (it doesn't violate any spec or standard). Questionable "feature" from a security POV, yes, but not "broken" (and it's supported by most client apps out there, unfortunately...) Whether we agree that it's a good feature or not (I don't consider it to be good), it's a very real problem that won't ever go away.
When you get to the general case of 'N' the feature being discussed
here is no
longer relevant. The original hypothesis is that only a cracker will
use N
different passwords on N different login attempts. If a legitimate user
is
using N different passwords on N tries, then the hypothesis fails and
there is
no validity to this feature at all.
It's not that a user will use N different passwords. It's differentiating between the attack, which uses N different passwords, and the bad user that uses the same password N times (because the had some client app save their password, then changed it without fixing the app).
If in fact a legitimate user only tries with 1 password, repeatedly,
then
storing (a hash of) only the last attempted password will be sufficient
to
detect this.
If you're storing only 1 password, and a cracker is attempting to break
in at
the same time that the user is trying to login, then you might as well
allow
the lockout to occur, because it will get a sysadmin's attention and
they need
to respond to the attack anyway.
The key is to differentiate between the two, and be able to lock in the case of the cracker, but not the bad user (even if both are happening at the same time).
If both *are* happening at the same time, it has to catch the attack - so if we see one process attempting many different passwords and at the same time see the same password being used over and over, it has to be able to lock because of the changing passwords. So tracking just the last password tried would not be sufficient, I don't think. Tracking the last pwdMaxFailure *unique* failed passwords that were attempted would, I think. I think once you hit pwdMaxFailure (or when the account is locked), you can stop recording things - once it's locked, you can't bind as it, so we don't have to track toward a lockout event. If the attack continues after we unlock it, it will quickly be locked again with minimal risk.
I think you'd have to store a hash of all failed passwords tried within the window of time defined.
Since there is already a counter for maximum number of failed attempts,
the
timestamp is superfluous.
The timestamp is to determine whether the password attempts occured within the window of time that matters, and to ignore/purge those that happen outside of it, and allow things to unlock after some period of time.
My thinking is that this would be in place of pwdFailureTime - i.e. instead of storing all the timestamps alone, what would matter is to just store the password hash and the last time that password was tried. If it accumulates too many values, the account may be locked. But instead of counting all failures, we just count the number of *unique* failures (and we need the password hash to implement the uniqueness, and the timestamp to see if it happened within pwdFailureCountInterval).
Effectively, it means before updating pwdFailureTime, we look in that to see if this password is listed there. If it is, we update the timestamp, instead of adding another value. If not, we add it with the current timestamp. Everything else probably works about the same as it does now.
If the number of values in this attribute exceed the number of max fails allowed, the account is locked. Timestamp is needed to eventually expire and remove it.
Removal should only occur when a successful login occurs. There's no
need for
a separate expiration period.
If the account is locked out, how does one successfully log in? 1) if the password is reset. 2) after some amount of time has passed (pwdFailureCountInterval). 3) ?...
Making security-related suggestions that you haven't fully thought
through yet
really isn't a good idea.
Let me rephrase. What I should have said was I have not discussed this with enough people to see if anyone else has thought of something I haven't, so I'm throwing this out for that discussion. At this point, I think I've thought it through enough - but do have concerns about the storage of these attempted passwords and the performance/complexity of implementing it that others may improve upon (or show good reason why this really is a bad idea :) This is where my hesitation towards this idea comes from).
If you only allow pwdMaxFailure attempts before locking the account,
there's
no point in even examining any passwords subsequent to the lockout
event. So
no, there should never be a need to store more than pwdMaxFailure
values.
That's pwdMaxFailure *unique* attempts - that is a significant distinction. And yes, once you hit pwdMaxFailure unique failed attempts - i.e. once the account is locked, you don't necessarily need to even process bind requests until the account is unlocked.
But again, the point of this discussion is that when a legitimate user
is
trying to login, you shouldn't need to recognize more than 1 bad
password anyway.
The point of this discussion is to enhance the password lockout policy to still work as intended (to stop brute force attacks), while ignoring the
"user has an old password configed in an app somewhere, which is not really an attack" case.
- Jeff