It should not be possible to hit the issue in the real world, but we better
play safe here.
In my tests I could only reproduce the issue by:
1. Taking a snapshot while logged into the ACP.
2. Starting the upgrade until the new cookies have been set.
3. Aborting the upgrade.
4. Rolling back the snapshot.
5. Trying again.
In this case the XSRF-TOKEN cookie is correctly signed and the session cookie
matches the actual session ID. However the sessionVariables are outdated due to
the rollback. The process will continue with the old SECURITY_TOKEN, failing
after the new files from 5.4 are deployed.
This issue is fixed by also checking the cookie against the current request and
the active session to ensure all the values are correctly in place.
Resolves #4052
$hasValidXsrfToken = false;
if (!empty($_COOKIE['XSRF-TOKEN'])) {
- if (CryptoUtil::validateSignedString($_COOKIE['XSRF-TOKEN'])) {
+ if (
+ // Check that the XSRF-TOKEN cookie is correctly signed.
+ CryptoUtil::validateSignedString($_COOKIE['XSRF-TOKEN'])
+ // Check that the current session value matches the cookie value.
+ && WCF::getSession()->checkSecurityToken($_COOKIE['XSRF-TOKEN'])
+ // Check that the 't' used for this request matches the cookie value.
+ && (
+ !empty($_REQUEST['t'])
+ && \hash_equals($_COOKIE['XSRF-TOKEN'], $_REQUEST['t'])
+ )
+ ) {
$hasValidXsrfToken = true;
}
}