RocketChat / Rocket.Chat

The communications platform that puts data protection first.
https://rocket.chat/
Other
40.24k stars 10.43k forks source link

[bug] 'Block failed login attempts by Username' not prevent to LDAP account to be locked #18939

Open ankar84 opened 4 years ago

ankar84 commented 4 years ago

Description:

https://github.com/RocketChat/Rocket.Chat/pull/17783 was introduced ability to block failed login attempts by Username and IP. It should mitigate LDAP accounts from locked-out, but in fact, it's not do that. I think, now it's only stops local accounts password brute-force, which is great actually. @MarcosSpessatto @rodrigok @sampaiodiego @pierre-lehnen-rc please take a look at that issue.

Steps to reproduce:

  1. Enable all options in Failed login Attempts section of Admin UI
  2. Try to login with LDAP account and wrong password 10 times (for example. You need more, then set in settings)
  3. Message warning shows that you temporarily blocked, but you still can do attempts to lockout LDAP account

Expected behavior:

When account is temporarily locked in Rocket Chat, there should not be authentication attempts to LDAP for LDAP users

Actual behavior:

In login page I see warning image But in fact all login attempts continue to ask LDAP server to authenticate user. Which lockout user, because password is wrong and Active Directory policy is set to temporarily (30 min) lock-out accounts after 5 failed login attempts. I see this in logs (Logs section) Here is my lockout settings image image

Server Setup Information:

Client Setup Information

Additional context

If account is locked in Rocket Chat side, all login attempts (LDAP) for that account should be stopped.

And about Rocket Chat blocking failed attempts I have 2 questions:

  1. Can Admin manually unlock blocked account?
  2. Can I see in logs, that account is locked temporarily?

Relevant logs:

LDAP ➔ Auth.info Not authenticated CN=Karlan Anton (Test1),OU=test,OU=Users,DC=company,DC=com
LDAPHandler ➔ info Wrong password for KarlanAAt01
LDAPHandler ➔ info Fallback to default account system { username: 'KarlanAAt01' }
Failed login detected - Username[unknown] ClientAddress[YYY.YYY.YYY.YYY] ForwardedFor[XXX.XXX.XXX.XXX, YYY.YYY.YYY.YYY] XRealIp[YYY.YYY.YYY.YYY] UserAgent[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36]
LDAP ➔ Search.info Idle
LDAP ➔ Connection.info Disconecting
aleadco commented 4 years ago

I am getting this same error using OAuth2

ankar84 commented 3 years ago

@pierre-lehnen-rc @sampaiodiego please add security tag to that issue

ankar84 commented 3 years ago

@pierre-lehnen-rc And another one thing. We are using KeyCloak to authenticate LDAP users in RC. It give us SSO on domain joined computers. When I did logoff on such domain computer in Chrome 86 I get this error in RC logs: Failed login detected - Username[unknown] ClientAddress[172.18.106.100] ForwardedFor[192.168.15.237, 172.18.106.100] XRealIp[undefined] UserAgent[Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36] where 192.168.15.237 my local IP and 172.18.106.100 IP of reverse proxy before RC I just logoff. And we still have default login form disabled, so I don't even have opportunity to login with it to get failed login. And it's reproduceable 100% (did try 2 times)

karatzanis commented 3 years ago

Both LDAP and Google OAuth reproduce the same behavior. I cannot offer my users the possibility to log in without creating one more set of credentials for rocket.chat. Is there any information (or solution) to this matter?

hans4rc commented 3 years ago

I use Google Authenticator and some of my users keep getting blocked. Not reproducible why. Even if I change the username or reset the 2FA, users remain blocked.

pkonnov commented 3 years ago

:v: In the ldap module, I make a check that is already in the chain of user authentication logic through possible services. This solution makes it possible to prevent unnecessary requests from being sent to ldap. I think you can create a function in app/authentication/server/startup/index.js or app/authentication/server/utils.js(for exapmle) and call it before sending requests to other authentication services(crawd, oauth, etc). Maybe someone has their own solutions to this bug if it's a bug?

Accounts.registerLoginHandler('ldap', function(loginRequest) {

        ...................

    try {
                // check if user is blocked
        let user = Promise.await(Users.findOneByUsername(loginRequest.username));
        const attemptsUntilBlock = settings.get('Block_Multiple_Failed_Logins_Attempts_Until_Block_by_User');

        let failedAttemptsSinceLastLogin;

        if (!user?.lastLogin) {
            failedAttemptsSinceLastLogin = Promise.await(ServerEvents.countFailedAttemptsByUsername(user.username));
        } else {
            failedAttemptsSinceLastLogin = Promise.await(ServerEvents.countFailedAttemptsByUsernameSince(user.username, new Date(user.lastLogin)));
        }

        if (attemptsUntilBlock && failedAttemptsSinceLastLogin > attemptsUntilBlock) {
            throw new Meteor.Error('error-login-blocked-for-user', 'Login has been temporarily blocked For User', {
                function: 'Accounts.registerLoginHandler',
            });
        }

        ldap.connectSync();
..............
ankar84 commented 3 years ago

@pierre-lehnen-rc can you implement that solution of @pkonnov to codebase?

alokraj68 commented 3 years ago

i am getting this issue even without LDAP enabled.

isikemre commented 2 years ago

Yes I am getting this issue even without LDAP enabled, too. (version 4.1.0) I figured out, that when "Failed Login Attempts" (Enable collect log in data) is enabled then users cannot register. When disabled everything works fine.

ankar84 commented 2 years ago

Still an issue in 4.2.0! User get locked in LDAP server but RC shows it soft locked in RC (in fact not). All failed attempts translated to LDAP server that leads to account lock out.

@pierre-lehnen-rc hey! Can you take a look at this solution?