Sign the session cookie
authorTim Düsterhus <duesterhus@woltlab.com>
Wed, 14 Oct 2020 09:30:08 +0000 (11:30 +0200)
committerTim Düsterhus <duesterhus@woltlab.com>
Thu, 15 Oct 2020 14:14:11 +0000 (16:14 +0200)
wcfsetup/install/files/lib/system/package/PackageInstallationDispatcher.class.php
wcfsetup/install/files/lib/system/session/ACPSessionFactory.class.php
wcfsetup/install/files/lib/system/session/SessionHandler.class.php

index 80df31f82f12bbf84c556f22cb23eccd46ee931c..857e4c46999c3209950720226a89f2001545b0e6 100644 (file)
@@ -36,6 +36,7 @@ use wcf\system\setup\Installer;
 use wcf\system\style\StyleHandler;
 use wcf\system\user\storage\UserStorageHandler;
 use wcf\system\WCF;
+use wcf\util\CryptoUtil;
 use wcf\util\FileUtil;
 use wcf\util\HeaderUtil;
 use wcf\util\JSON;
@@ -231,9 +232,14 @@ class PackageInstallationDispatcher {
                                        ]);
                                        
                                        $statement->execute([
-                                               \bin2hex(\random_bytes(20)),
+                                               $signatureSecret = \bin2hex(\random_bytes(20)),
                                                'signature_secret'
                                        ]);
+                                       define('SIGNATURE_SECRET', $signatureSecret);
+                                       HeaderUtil::setCookie(
+                                               "acp_session",
+                                               CryptoUtil::createSignedString(WCF::getSession()->sessionID)
+                                       );
                                        
                                        if (WCF::getSession()->getVar('__wcfSetup_developerMode')) {
                                                $statement->execute([
index 3eb87e951e01e18bdb95b16ea4f2cf19994bc5c7..d71820748f277db5783cc6d9eb462750c9d6850b 100644 (file)
@@ -55,16 +55,4 @@ class ACPSessionFactory {
        protected function init() {
                SessionHandler::getInstance()->initSession();
        }
-       
-       /**
-        * @deprecated 5.4 - Sessions are fully managed by SessionHandler.
-        */
-       protected function readSessionID() {
-               // get sessionID from cookie
-               if (isset($_COOKIE[COOKIE_PREFIX.$this->cookieSuffix.'session'])) {
-                       return $_COOKIE[COOKIE_PREFIX.$this->cookieSuffix.'session'];
-               }
-               
-               return '';
-       }
 }
index 7664a91957f3101e47dbb454bc8d20211886826d..2868bcd7817e1ff5a6e533b9e866ce563f9a7f80 100644 (file)
@@ -16,6 +16,7 @@ use wcf\system\user\storage\UserStorageHandler;
 use wcf\system\SingletonFactory;
 use wcf\system\WCF;
 use wcf\system\WCFACP;
+use wcf\util\CryptoUtil;
 use wcf\util\HeaderUtil;
 use wcf\util\UserUtil;
 
@@ -179,6 +180,34 @@ final class SessionHandler extends SingletonFactory {
         */
        public function setHasValidCookie($hasValidCookie) { }
        
+       /**
+        * Returns the session ID stored in the session cookie or `null`.
+        */
+       private function getSessionIdFromCookie(): ?string {
+               $cookieName = COOKIE_PREFIX.($this->isACP ? 'acp' : 'user')."_session";
+               
+               if (isset($_COOKIE[$cookieName])) {
+                       if (!PACKAGE_ID) {
+                               return $_COOKIE[$cookieName];
+                       }
+                       
+                       return CryptoUtil::getValueFromSignedString($_COOKIE[$cookieName]);
+               }
+               
+               return null;
+       }
+       
+       /**
+        * Returns the signed session ID for use in a cookie.
+        */
+       private function getSessionIdForCookie(string $sessionID): string {
+               if (!PACKAGE_ID) {
+                       return $sessionID;
+               }
+               
+               return CryptoUtil::createSignedString($sessionID);
+       }
+       
        /**
         * Returns true if client provided a valid session cookie.
         * 
@@ -186,10 +215,7 @@ final class SessionHandler extends SingletonFactory {
         * @since       3.0
         */
        public function hasValidCookie(): bool {
-               $cookieName = COOKIE_PREFIX.($this->isACP ? 'acp' : 'user')."_session";
-               $sessionID = $_COOKIE[$cookieName] ?? null;
-               
-               return $sessionID === $this->sessionID;
+               return $this->getSessionIdFromCookie() === $this->sessionID;
        }
        
        /**
@@ -211,8 +237,7 @@ final class SessionHandler extends SingletonFactory {
         * Loads the session matching the session cookie.
         */
        public function loadFromCookie() {
-               $cookieName = COOKIE_PREFIX.($this->isACP ? 'acp' : 'user')."_session";
-               $sessionID = $_COOKIE[$cookieName] ?? null;
+               $sessionID = $this->getSessionIdFromCookie();
                
                $hasSession = false;
                if ($sessionID) {
@@ -414,7 +439,11 @@ final class SessionHandler extends SingletonFactory {
                
                // Refresh cookie.
                if ($this->user->userID && !$this->isACP) {
-                       HeaderUtil::setCookie(($this->isACP ? 'acp' : 'user')."_session", $this->sessionID, TIME_NOW + 86400 * 14);
+                       HeaderUtil::setCookie(
+                               ($this->isACP ? 'acp' : 'user')."_session",
+                               $this->getSessionIdForCookie($this->sessionID),
+                               TIME_NOW + 86400 * 14
+                       );
                }
                
                // Fetch legacy session.
@@ -470,7 +499,10 @@ final class SessionHandler extends SingletonFactory {
                        serialize([]),
                ]);
                
-               HeaderUtil::setCookie(($this->isACP ? 'acp' : 'user')."_session", $this->sessionID);
+               HeaderUtil::setCookie(
+                       ($this->isACP ? 'acp' : 'user')."_session",
+                       $this->getSessionIdForCookie($this->sessionID)
+               );
                
                $this->variables = [];
                $this->user = new User(null);