Commit 0a6cd619 by Qiang Xue

Fixes #7051: Added support for preventing swapping values between different cookies

parent e05595e0
...@@ -13,7 +13,8 @@ Yii Framework 2 Change Log ...@@ -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 #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 #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 #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 #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) - 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)
......
...@@ -1212,10 +1212,18 @@ class Request extends \yii\base\Request ...@@ -1212,10 +1212,18 @@ class Request extends \yii\base\Request
throw new InvalidConfigException(get_class($this) . '::cookieValidationKey must be configured with a secret key.'); throw new InvalidConfigException(get_class($this) . '::cookieValidationKey must be configured with a secret key.');
} }
foreach ($_COOKIE as $name => $value) { 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([ $cookies[$name] = new Cookie([
'name' => $name, 'name' => $name,
'value' => @unserialize($value), 'value' => $data[1],
'expire'=> null 'expire'=> null
]); ]);
} }
...@@ -1283,10 +1291,8 @@ class Request extends \yii\base\Request ...@@ -1283,10 +1291,8 @@ class Request extends \yii\base\Request
{ {
$token = Yii::$app->getSecurity()->generateRandomString(); $token = Yii::$app->getSecurity()->generateRandomString();
if ($this->enableCsrfCookie) { if ($this->enableCsrfCookie) {
$config = $this->csrfCookie; $cookie = $this->createCsrfCookie($token);
$config['name'] = $this->csrfParam; Yii::$app->getResponse()->getCookies()->add($cookie);
$config['value'] = $token;
Yii::$app->getResponse()->getCookies()->add(new Cookie($config));
} else { } else {
Yii::$app->getSession()->set($this->csrfParam, $token); Yii::$app->getSession()->set($this->csrfParam, $token);
} }
...@@ -1325,14 +1331,15 @@ class Request extends \yii\base\Request ...@@ -1325,14 +1331,15 @@ class Request extends \yii\base\Request
/** /**
* Creates a cookie with a randomly generated CSRF token. * Creates a cookie with a randomly generated CSRF token.
* Initial values specified in [[csrfCookie]] will be applied to the generated cookie. * Initial values specified in [[csrfCookie]] will be applied to the generated cookie.
* @param string $token the CSRF token
* @return Cookie the generated cookie * @return Cookie the generated cookie
* @see enableCsrfValidation * @see enableCsrfValidation
*/ */
protected function createCsrfCookie() protected function createCsrfCookie($token)
{ {
$options = $this->csrfCookie; $options = $this->csrfCookie;
$options['name'] = $this->csrfParam; $options['name'] = $this->csrfParam;
$options['value'] = Yii::$app->getSecurity()->generateRandomString(); $options['value'] = $token;
return new Cookie($options); return new Cookie($options);
} }
......
...@@ -375,7 +375,7 @@ class Response extends \yii\base\Response ...@@ -375,7 +375,7 @@ class Response extends \yii\base\Response
foreach ($this->getCookies() as $cookie) { foreach ($this->getCookies() as $cookie) {
$value = $cookie->value; $value = $cookie->value;
if ($cookie->expire != 1 && isset($validationKey)) { 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); setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment