| The authentication failure strategies selected in the Authentication administration section (CAPTCHA, Disable account) are cached in memory for the whole farm and rebuilt when the configuration changes. This cache isn't safe when several requests use it at the same time: logins, display of the login page and REST requests using basic authentication all read it. Impact When an administrator changes the failure strategies while other users are logging in, two requests can rebuild the cache at the same time. The cached list of strategies can then stay damaged until the strategies are changed again or XWiki is restarted:
- A user who reaches the maximum number of failed attempts gets an error page instead of the login form, and can't log in any more, even with the correct password, because every login attempt for this user fails with a NullPointerException.
- A selected strategy can be skipped or applied twice, e.g. the account isn't disabled, or the CAPTCHA isn't requested, although the administrator selected it.
A request can also use an incomplete list of strategies while another request is rebuilding it. In a farm where wikis select different strategies, the single cache is rebuilt each time a request comes from a different wiki than the previous one, which makes the problem above much more likely as soon as users log in to several wikis at the same time. A request can then also apply the strategies selected in another wiki. Example LoginProtectionIT#disableAccountStrategy failed on CI when the 4th failed login triggered the strategies, and the login page showed an error (stable-18.9.x build 10):
ERROR x.x.u.i.x.XWikiAuthServiceImpl - Failed to authenticate
java.lang.NullPointerException: Cannot read field "next" because "this.next" is null
at java.base/java.util.LinkedList$ListItr.next(LinkedList.java:905)
at org.xwiki.security.authentication.internal.DefaultAuthenticationFailureManager.recordAuthenticationFailure(DefaultAuthenticationFailureManager.java:217)
at org.xwiki.security.authentication.AuthenticationFailureManager.recordAuthenticationFailure(AuthenticationFailureManager.java:50)
at com.xpn.xwiki.user.impl.xwiki.MyFormAuthenticator.processLogin(MyFormAuthenticator.java:255)
The same request then failed again with the same exception while displaying the error message on the login page (AuthenticationScriptService#getErrorMessage), showing that the cached list itself was damaged. |