Check the XSRF-TOKEN cookie against the active request during 5.4 upgrade
authorTim Düsterhus <duesterhus@woltlab.com>
Mon, 8 Mar 2021 10:02:22 +0000 (11:02 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Mon, 8 Mar 2021 10:02:56 +0000 (11:02 +0100)
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

wcfsetup/install/files/acp/update_com.woltlab.wcf_5.4_session_1_cookies.php

index 4bd82f9621dae9d58d731d9285ee6fc2b6c73ffc..ca558c9795b0ec759f3ee49bfc893322613c0e92 100644 (file)
@@ -32,7 +32,17 @@ if (!empty($_COOKIE[COOKIE_PREFIX . "user_session"])) {
 
 $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;
     }
 }