Some browsers have the feature of restoring all tabs on launch. If numerous tabs are opened, this sends multiple requests to Joomla! in parallel (even more if keepalive pings are "remembered" and issued at the same time than tab requests, which I have seen in the wild) with the same value of the authentication cookie. This is identified as an attack, resulting in user sessions being purged.
The issue comes from plugins/authentication/cookie/src/Extension/Cookie.php, whose role is:
onUserAuthenticate: check that the cookie is correct w.r.t. user_keys contentonUserAfterLogin: update the cookie and the user_keys entry, or create both on first login when "remember me" option is setWhen several request arrives at the same time, then:
onUserAuthenticate, then land in onUserAfterLogin which modifies (several times) the cookie and the db. I assume this is in all cases unwanted behavior and a vulnerability.onUserAuthenticate because the db was updateduser_keys is destroyedUse transaction on the db with a lock at the row granularity to serialize access to the corresponding user_keys entry. This means that the cookie update is moved to onUserAuthenticate (and creation stays in onUserAfterLogin), so that the transaction starts and commit / abort in the same function scope. The corresponding requests are:
START TRANSACTION;
SELECT .... from user_keys WHERE cookie_is_valid FOR UPDATE; # blocking read, serialization point
UPDATE user_keys SET .... WHERE cookie_is_valid;
COMMIT;This will guarantee that one cookie gets updated only once, and all subsequent requests will fail, avoiding both the security issue mentioned earlier and the nondeterministic way the user's cookie is updated when several updates to the db are done in parallel.
When the transaction fails because the cookie is not valid, it is either an attack or multiple request. My guess would be to throw an error message similar to "too many autologin tentatives, please try again" and not delete all the sessions neither the cookie, as it may be updated (or have been updated) by another request / tab.
PoC code is available in this patch. Note that there is a subtlety: cookie login is still attempted if the cookie is present but invalid and a user logins, case in which the message should not be displayed (which we can detect by the presence of input->getVar('username').
FOR UPDATE is currently not wrapped on Joomla! 6 mysqli back-end. This would need to be done (or hacked) for this fix to be integrated. Do we want that?| Labels |
Added:
No Code Attached Yet
|
||