Skip to content

Locked account produces "Invalid credentials" message #50028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
antfarmer opened this issue Apr 15, 2023 · 8 comments · Fixed by #58300
Closed

Locked account produces "Invalid credentials" message #50028

antfarmer opened this issue Apr 15, 2023 · 8 comments · Fixed by #58300

Comments

@antfarmer
Copy link

Symfony version(s) affected

5.4.21+

Description

When using the 'hide_user_not_found' feature (enabled by default), a user who tries to login with the proper credentials and has a locked or disabled account, will receive the "Invalid credentials" message. This is unexpected as the user is found, but the account is locked or disabled. The exception thrown for these cases are either the LockedException, DisabledException, or AccountExpiredException. One would expect this message only for a UsernameNotFoundException, not including cases where the user is found, but is inactive or locked out in some way. This used to provide useful feedback for our clients so they would not waste time trying to reset their password. I guess some could argue it is better to obfuscate the error in all cases, but this seems a bit paranoid, and again the feature seems improperly named. I would propose to either rename this or better yet, separate this into two features: e.g. hideUserNotFoundExceptions and hideAllAuthExceptions.

How to reproduce

Setup the application as normal. Implement a UserCheckerInterface on the main secured firewall. Throw an AccountStatusException in the checkPostAuth function. The exception can be the LockedException, DisabledException, or AccountExpiredException. Notice the message to the user is "Invalid (or Bad) credentials".

Possible Solution

Looking at the code in AuthenticatorManager#handleAuthenticationFailure:271 it does seem like a bug or at least a feature with a misleading name: hideUserNotFoundExceptions.

Replacing that conditional block with this made it work as expected and as previously:

if ($this->hideUserNotFoundExceptions && ($authenticationException instanceof UsernameNotFoundException 
		|| $authenticationException instanceof UserNotFoundException)) {
	$authenticationException = new BadCredentialsException('Bad credentials.', 0, $authenticationException);
}

I believe this block of code is also in a few other classes in the codebase, so this would also would be nice to address.

This is similar to this previously discussed here #42793, but has already been closed.

Additional Context

No response

@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@antfarmer
Copy link
Author

Yes this is still relevant.

@antfarmer antfarmer reopened this Nov 1, 2023
@antfarmer
Copy link
Author

This is still relevant. The only workaround seems to be disabling the hide_user_not_found security setting and then checking the last authentication exception in the login controller and replacing a UserNotFoundException with a BadCredentials exception. This does seem to be brittle and better handled in the framework logic.

security.yaml:

security:
    hide_user_not_found: false

SecurityController.php:

		$authEx = $authUtils->getLastAuthenticationError(true);
		if ($authEx !== null) {
			// TODO due to what seems to be a bug in AuthenticatorManager#handleAuthenticationFailure:271
			// see https://github.com/symfony/symfony/issues/42793
			if ($authEx instanceof UserNotFoundException) {
				$authEx = new BadCredentialsException('Bad credentials.', 0, $authEx);
			}
		}
		return $authEx;

@carsonbot carsonbot removed the Stalled label Nov 1, 2023
@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@carsonbot
Copy link

Hello? This issue is about to be closed if nobody replies.

@core23
Copy link
Contributor

core23 commented May 20, 2024

Can confirm the issue. This looks like a bug, because the hideUserNotFoundExceptions toggle does not only hide "user not found exception" but also other technical errors like account is blocked

@chalasr
Copy link
Member

chalasr commented May 20, 2024

Quoting #56830 (comment):

The fact that whether built-in AccountStatusException are caught or not depends on the hide_user_not_found flag although they are not UserNotFoundException might sound weird, yet it is on purpose.
We did this as part of a security fix 3 years ago. Reasoning was that the use case such exceptions serve is pretty much the same as UserNotFoundException ones regarding user enumeration.

So if we want to change this, that would definitely be a new feature.
Also it should not be about suddenly stopping to catch those, first because that would be too much of a BC break and also because it would go against the decision that led to the CVE mentioned above. What could be done is to rename the flag for the sake of clarity or split it in two. Given the traction on related issues, I would be fine doing so.

@antfarmer
Copy link
Author

Thanks for posting here on this bug fix.

Quoting #56830 (comment)

I'm not clear; is this fix now to revert the changes to only mask UserNotFoundException's?

Personally, I'm fine with that because I do not see much benefit to masking locked accounts. The account would be locked and there would normally be nothing a legitimate or malicious user could do to unlock the account. Only to accommodate others on this, it may be worth considering having two settings, eg. hideUserNotFoundExceptions and hideAllAuthExceptions.

In my project I see there are at least 3 places where this logic is implemented:

* security-http: Symfony\Component\Security\Http\Authentication\AuthenticatorManager: handleAuthenticationFailure

* security-core: Symfony\Component\Security\Core\Authentication\Provider\UserAuthenticationProvider: authenticate

* security-guard: Symfony\Component\Security\Guard\Firewall\GuardAuthenticationListener: executeGuardAuthenticator

Will these also be updated or are these others being phased out? Also, I assume this will be patched in 5.4+ going forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants