CVE-2021-3818 (published 2021-09-27T13:15Z)

grav is vulnerable to Reliance on Cookies without Validation and Integrity Checking

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:N/I:P/A:N)
CVSS v3 base score: 5.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N)

Weakness information:
cwe_id: CWE-565
cwe_name: Reliance on Cookies without Validation and Integrity Checking
description: The product relies on the existence or values of cookies when performing security-critical operations, but it does not properly ensure that the setting is valid for the associated user.
extended_description: Attackers can easily modify cookies, within the browser or by implementing the client-side code outside of the browser. Reliance on cookies without detailed validation and integrity checking can allow attackers to bypass authentication, conduct injection attacks such as SQL injection and cross-site scripting, or otherwise modify inputs in unexpected ways.
         

Fix information:
repo_url: https://github.com/getgrav/grav
commit_details: repo_url: https://github.com/getgrav/grav
author: Matias Griese
author_date: 2021-09-14 18:28:07+03:00
msg: Fixed `Session::setFlashCookieObject()` to use the same options as the main session cookie
repository: repo_url: https://github.com/getgrav/grav
repo_name: getgrav/grav
description: Modern, Crazy Fast, Ridiculously Easy and Amazingly Powerful Flat-File CMS powered by PHP, Markdown, Twig, and Symfony
repo_language: PHP
owner: getgrav
file_changes: filename: CHANGELOG.md
change_type: ModificationType.MODIFY
diff: @@ -13,6 +13,7 @@
     * Fixed validation of `number` type [#3433](https://github.com/getgrav/grav/issues/3433)
     * Fixed excessive `security.yaml` file creation [#3432](https://github.com/getgrav/grav/issues/3432)
     * Fixed incorrect port :0 with nginx unix socket setup [#3439](https://github.com/getgrav/grav/issues/3439)
+    * Fixed `Session::setFlashCookieObject()` to use the same options as the main session cookie
 
 # v1.7.20
 ## 09/01/2021

programming_language: Markdown
filename: Session.php
change_type: ModificationType.MODIFY
diff: @@ -12,6 +12,7 @@ namespace Grav\Common;
 use Grav\Common\Form\FormFlash;
 use Grav\Events\SessionStartEvent;
 use Grav\Plugin\Form\Forms;
+use JsonException;
 use function is_string;
 
 /**
@@ -148,10 +149,11 @@ class Session extends \Grav\Framework\Session\Session
      * @param mixed $object
      * @param int $time
      * @return $this
+     * @throws JsonException
      */
     public function setFlashCookieObject($name, $object, $time = 60)
     {
-        setcookie($name, json_encode($object), time() + $time, '/');
+        setcookie($name, json_encode($object, JSON_THROW_ON_ERROR), $this->getCookieOptions($time));
 
         return $this;
     }
@@ -161,13 +163,15 @@ class Session extends \Grav\Framework\Session\Session
      *
      * @param string $name
      * @return mixed|null
+     * @throws JsonException
      */
     public function getFlashCookieObject($name)
     {
         if (isset($_COOKIE[$name])) {
-            $object = json_decode($_COOKIE[$name], false);
-            setcookie($name, '', time() - 3600, '/');
-            return $object;
+            $cookie = $_COOKIE[$name];
+            setcookie($name, '', $this->getCookieOptions(-42000));
+
+            return json_decode($cookie, false, 512, JSON_THROW_ON_ERROR);
         }
 
         return null;

programming_language: PHP
filename: Session.php
change_type: ModificationType.MODIFY
diff: @@ -338,23 +338,12 @@ class Session implements SessionInterface
     {
         $name = $this->getName();
         if (null !== $name) {
-            $params = session_get_cookie_params();
-
-            $cookie_options = array (
-                'expires'  => time() - 42000,
-                'path'     => $params['path'],
-                'domain'   => $params['domain'],
-                'secure'   => $params['secure'],
-                'httponly' => $params['httponly'],
-                'samesite' => $params['samesite']
-            );
-
             $this->removeCookie();
 
             setcookie(
                 session_name(),
                 '',
-                $cookie_options
+                $this->getCookieOptions(-42000)
             );
         }
 
@@ -463,27 +452,36 @@ class Session implements SessionInterface
     }
 
     /**
-     * @return void
+     * Store something in cookie temporarily.
+     *
+     * @param int|null $lifetime
+     * @return array
      */
-    protected function setCookie(): void
+    public function getCookieOptions(int $lifetime = null): array
     {
         $params = session_get_cookie_params();
 
-        $cookie_options = array (
-            'expires'  => time() + $params['lifetime'],
+        return [
+            'expires'  => time() + ($lifetime ?? $params['lifetime']),
             'path'     => $params['path'],
             'domain'   => $params['domain'],
             'secure'   => $params['secure'],
             'httponly' => $params['httponly'],
             'samesite' => $params['samesite']
-        );
+        ];
+    }
 
+    /**
+     * @return void
+     */
+    protected function setCookie(): void
+    {
         $this->removeCookie();
 
         setcookie(
             session_name(),
             session_id(),
-            $cookie_options
+            $this->getCookieOptions()
         );
     }
 

programming_language: PHP