Reputation: 68
I am using Spring Security to support authentication and authorisation in my application. I've customised a few aspects of the security context, but I don't think this plays a part in my question / issue.
I'm currently using Spring 3.1.2.RELEASE and Spring Security 3.1.3.RELEASE, but I'm about to update to the latest versions.
I think there is a bug with the AbstractUserDetailsAuthenticationProvider$DefaultPreAuthenticationChecks()
inner class that I've just found, described below:
If I try to log in with a user and a bad (incorrect) password, but this user is found in my user repository, and they are either locked, disabled or the account is expired, then Spring Security responds with the LockedException
, DisabledException
, or AccountExpiredException
.
However, from this response, I've just determined that the user exists in the repository and even though I've just guessed the password, and don't yet know if it's right or wrong! Rather, Spring Security should respond primarily with a BadCredentialsException
, and only if the credentials are authenticated respond with the locked, disabled or account expired exceptions.
Has anyone else seen / reported this behaviour? I've searched but couldn't see this anywhere!
Thanks Rob
I've just upgraded to Spring 3.2.1.RELEASE and Spring Security 3.2.0.M1 and this behaviour still remains the same.
Upvotes: 3
Views: 812
Reputation: 17518
This would only be a problem if the exception's message made it into the HTTP response. Ispecting the code shows that it's not the case if you use the default namespace configuration (<security:form-login>
), because all an attacker gets as response is a HTTP redirect to the login page, regardless of what kind of AuthenticationException
were thrown on the server side.
Reading the code shows however that it is possible to configure the AuthenticationFailureHandler
in a way that results in the exposure of this information.
Snippet from SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure()
:
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
"Authentication Failed: " + exception.getMessage());
}
If you meant this problem then I think you are kind of right, because sending back the exception message is definitely more than the client side should see. Although the developer has to make some effort to achive this insecure behavior, which is setting the defaultFailureUrl
to null. If I'm not mistaken, this is not even possible by purely using the namespace configuration (there is a default if it's not explicitly set).
Upvotes: 1