From 0a6cd6190b851db89120572259ae8ca0ade9c2cb Mon Sep 17 00:00:00 2001 From: Qiang Xue Date: Wed, 28 Jan 2015 22:29:37 -0500 Subject: [PATCH] Fixes #7051: Added support for preventing swapping values between different cookies --- framework/CHANGELOG.md | 3 ++- framework/web/Request.php | 23 +++++++++++++++-------- framework/web/Response.php | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index b6512ac..1ec6dbb 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -13,7 +13,8 @@ Yii Framework 2 Change Log - Enh #6697: Added `yii\helpers\Url::current()` method that allows adding or removing parameters from current URL (samdark, callmez) - Enh #6852: Added `yii\helpers\BaseHtmlPurifier::helpers()` in order to be able to configure `HtmlPurifier` helper globally via subclassing (Alex-Code) - Enh #6882: Added `yii\web\ErrorHandler::getTypeUrl()` in order to allow providing custom types/classes/methods URLs for subclasses (brandonkelly) -- Enh #6896: Added `yii\log\FileTarget::$enableRotation` to allow disabling log rotation when external tools are configured for this (cebe) +- Enh #6896: Added `yii\log\FileTarget::$enableRotation` to allow disabling log rotation when external tools are configured for this (cebe) +- Enh #7051: Added support for preventing swapping values between different cookies (pavimus, qiangxue) - Chg #5690: adjusted paths in message config generated by `yii message/config` to reflect directory structure better (mikehaertl, samdark) - Chg #6661: Hyperlinks that are enclosed within an exist form will use the same form for submission if they specify both of the `href` and `data-method` attributes (qiangxue) diff --git a/framework/web/Request.php b/framework/web/Request.php index 766581c..d2490a0 100644 --- a/framework/web/Request.php +++ b/framework/web/Request.php @@ -1212,10 +1212,18 @@ class Request extends \yii\base\Request throw new InvalidConfigException(get_class($this) . '::cookieValidationKey must be configured with a secret key.'); } foreach ($_COOKIE as $name => $value) { - if (is_string($value) && ($value = Yii::$app->getSecurity()->validateData($value, $this->cookieValidationKey)) !== false) { + if (!is_string($value)) { + continue; + } + $data = Yii::$app->getSecurity()->validateData($value, $this->cookieValidationKey); + if ($data === false) { + continue; + } + $data = @unserialize($data); + if (is_array($data) && isset($data[0], $data[1]) && $data[0] === $name) { $cookies[$name] = new Cookie([ 'name' => $name, - 'value' => @unserialize($value), + 'value' => $data[1], 'expire'=> null ]); } @@ -1283,10 +1291,8 @@ class Request extends \yii\base\Request { $token = Yii::$app->getSecurity()->generateRandomString(); if ($this->enableCsrfCookie) { - $config = $this->csrfCookie; - $config['name'] = $this->csrfParam; - $config['value'] = $token; - Yii::$app->getResponse()->getCookies()->add(new Cookie($config)); + $cookie = $this->createCsrfCookie($token); + Yii::$app->getResponse()->getCookies()->add($cookie); } else { Yii::$app->getSession()->set($this->csrfParam, $token); } @@ -1325,14 +1331,15 @@ class Request extends \yii\base\Request /** * Creates a cookie with a randomly generated CSRF token. * Initial values specified in [[csrfCookie]] will be applied to the generated cookie. + * @param string $token the CSRF token * @return Cookie the generated cookie * @see enableCsrfValidation */ - protected function createCsrfCookie() + protected function createCsrfCookie($token) { $options = $this->csrfCookie; $options['name'] = $this->csrfParam; - $options['value'] = Yii::$app->getSecurity()->generateRandomString(); + $options['value'] = $token; return new Cookie($options); } diff --git a/framework/web/Response.php b/framework/web/Response.php index 68a63cc..4218e2a 100644 --- a/framework/web/Response.php +++ b/framework/web/Response.php @@ -375,7 +375,7 @@ class Response extends \yii\base\Response foreach ($this->getCookies() as $cookie) { $value = $cookie->value; if ($cookie->expire != 1 && isset($validationKey)) { - $value = Yii::$app->getSecurity()->hashData(serialize($value), $validationKey); + $value = Yii::$app->getSecurity()->hashData(serialize([$cookie->name, $value]), $validationKey); } setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); }