Commit 0a6cd619 by Qiang Xue

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

parent e05595e0
......@@ -14,6 +14,7 @@ Yii Framework 2 Change Log
- 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 #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)
......
......@@ -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);
}
......
......@@ -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);
}
......
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