Browse Source

Fixes #17353: Added `sameSite` support for `yii\web\Cookie` and `yii\web\Session::cookieParams`

tags/2.0.21
rhertogh 5 years ago committed by Alexander Makarov
parent
commit
1ed6ec1e5c
  1. 36
      docs/guide/runtime-sessions-cookies.md
  2. 9
      docs/guide/security-best-practices.md
  3. 1
      framework/CHANGELOG.md
  4. 30
      framework/web/Cookie.php
  5. 16
      framework/web/Response.php
  6. 20
      framework/web/Session.php

36
docs/guide/runtime-sessions-cookies.md

@ -332,11 +332,6 @@ examples, the [[yii\web\Cookie]] class also defines other properties to fully re
information, such as [[yii\web\Cookie::domain|domain]], [[yii\web\Cookie::expire|expire]]. You may configure these
properties as needed to prepare a cookie and then add it to the response's cookie collection.
> Note: For better security, the default value of [[yii\web\Cookie::httpOnly]] is set to `true`. This helps mitigate
the risk of a client-side script accessing the protected cookie (if the browser supports it). You may read
the [httpOnly wiki article](https://www.owasp.org/index.php/HttpOnly) for more details.
### Cookie Validation <span id="cookie-validation"></span>
When you are reading and sending cookies through the `request` and `response` components as shown in the last
@ -369,3 +364,34 @@ return [
> Info: [[yii\web\Request::cookieValidationKey|cookieValidationKey]] is critical to your application's security.
It should only be known to people you trust. Do not store it in the version control system.
## Security settings
Both [[yii\web\Cookie]] and [[yii\web\Session]] support the following security flags:
### httpOnly
For better security, the default value of [[yii\web\Cookie::httpOnly]] and the 'httponly' parameter of
[[yii\web\Session::cookieParams]] is set to `true`. This helps mitigate the risk of a client-side script accessing
the protected cookie (if the browser supports it).
You may read the [HttpOnly wiki article](https://www.owasp.org/index.php/HttpOnly) for more details.
### secure
The purpose of the secure flag is to prevent cookies from being send in clear text. If the browser supports the
secure flag it will only include the cookie when the request is sent over a secure (TLS) connection.
You may read the [SecureFlag wiki article](https://www.owasp.org/index.php/SecureFlag) for more details.
### sameSite
Starting with Yii 2.0.21 the [[yii\web\Cookie::sameSite]] setting is supported. It requires PHP version 7.3.0 or higher.
The purpose of the `sameSite` setting is to prevent CSRF (Cross-Site Request Forgery) attacks.
If the browser supports the `sameSite` setting it will only include the cookie according to the specified policy ('Lax' or 'Strict').
You may read the [SameSite wiki article](https://www.owasp.org/index.php/SameSite) for more details.
For better security, an exception will be thrown if `sameSite` is used with an unsupported version of PHP.
To use this feature across different PHP versions check the version first. E.g.
```php
[
'sameSite' => PHP_VERSION_ID >= 70300 ? yii\web\Cookie::SAME_SITE_LAX : null,
]
```
> Note: Since not all browsers support the `sameSite` setting yet, it is still strongly recommended to also include
[additional CSRF protection](security-best-practices.md#avoiding-csrf).

9
docs/guide/security-best-practices.md

@ -253,9 +253,14 @@ class ContactAction extends Action
> Warning: Disabling CSRF will allow any site to send POST requests to your site. It is important to implement extra validation such as checking an IP address or a secret token in this case.
> Note: Since version 2.0.21 Yii supports the `sameSite` cookie setting (requires PHP version 7.3.0 or higher).
Setting the `sameSite` cookie setting does not make the above obsolete since not all browsers support the setting yet.
See the [Sessions and Cookies sameSite option](runtime-sessions-cookies.md#samesite) for more information.
Further reading on the topic:
- <https://www.owasp.org/index.php/CSRF>
- <https://www.owasp.org/index.php/SameSite>
Avoiding file exposure
@ -301,6 +306,10 @@ provided by the H5BP project:
- [IIS](https://github.com/h5bp/server-configs-iis).
- [Lighttpd](https://github.com/h5bp/server-configs-lighttpd).
> Note: When TLS is configured it is recommended that (session) cookies are send over TLS exclusively.
This is achieved by setting the `secure` flag for sessions and/or cookies.
See the [Sessions and Cookies secure flag](runtime-sessions-cookies.md#secure) for more information.
Secure Server configuration
---------------------------

1
framework/CHANGELOG.md

@ -7,6 +7,7 @@ Yii Framework 2 Change Log
- Bug #17341: Fixed error from yii.activeForm.js in strict mode (mikehaertl)
- Enh #17345: Improved performance of `yii\db\Connection::quoteColumnName()` (brandonkelly)
- Enh #17348: Improved performance of `yii\db\Connection::quoteTableName()` (brandonkelly)
- Enh #17353: Added `sameSite` support for `yii\web\Cookie` and `yii\web\Session::cookieParams` (rhertogh)
2.0.20 June 04, 2019

30
framework/web/Cookie.php

@ -18,6 +18,23 @@ namespace yii\web;
class Cookie extends \yii\base\BaseObject
{
/**
* SameSite policy Lax will prevent the cookie from being sent by the browser in all cross-site browsing context
* during CSRF-prone request methods (e.g. POST, PUT, PATCH etc).
* E.g. a POST request from https://otherdomain.com to https://yourdomain.com will not include the cookie, however a GET request will.
* When a user follows a link from https://otherdomain.com to https://yourdomain.com it will include the cookie
* @see $sameSite
*/
const SAME_SITE_LAX = 'Lax';
/**
* SameSite policy Strict will prevent the cookie from being sent by the browser in all cross-site browsing context
* regardless of the request method and even when following a regular link.
* E.g. a GET request from https://otherdomain.com to https://yourdomain.com or a user following a link from
* https://otherdomain.com to https://yourdomain.com will not include the cookie.
* @see $sameSite
*/
const SAME_SITE_STRICT = 'Strict';
/**
* @var string name of the cookie
*/
public $name;
@ -48,6 +65,19 @@ class Cookie extends \yii\base\BaseObject
* such as JavaScript, which can effectively help to reduce identity theft through XSS attacks.
*/
public $httpOnly = true;
/**
* @var string SameSite prevents the browser from sending this cookie along with cross-site requests.
* Please note that this feature is only supported since PHP 7.3.0
* For better security, an exception will be thrown if `sameSite` is set while using an unsupported version of PHP.
* To use this feature across different PHP versions check the version first. E.g.
* ```php
* $cookie->sameSite = PHP_VERSION_ID >= 70300 ? yii\web\Cookie::SAME_SITE_LAX : null,
* ```
* See https://www.owasp.org/index.php/SameSite for more information about sameSite.
*
* @since 2.0.21
*/
public $sameSite;
/**

16
framework/web/Response.php

@ -401,7 +401,21 @@ class Response extends \yii\base\Response
if ($cookie->expire != 1 && isset($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);
if (PHP_VERSION_ID >= 70300) {
setcookie($cookie->name, $value, [
'expires' => $cookie->expire,
'path' => $cookie->path,
'domain' => $cookie->domain,
'secure' => $cookie->secure,
'httpOnly' => $cookie->httpOnly,
'sameSite' => !empty($cookie->sameSite) ? $cookie->sameSite : null,
]);
} else {
if (!is_null($cookie->sameSite)) {
throw new InvalidConfigException(get_class($cookie) . '::sameSite is not supported by PHP versions < 7.3.0 (set it to null in this environment)');
}
setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly);
}
}
}

20
framework/web/Session.php

@ -367,6 +367,16 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
* The cookie parameters passed to this method will be merged with the result
* of `session_get_cookie_params()`.
* @param array $value cookie parameters, valid keys include: `lifetime`, `path`, `domain`, `secure` and `httponly`.
* Starting with Yii 2.0.21 `sameSite` is also supported. It requires PHP version 7.3.0 or higher.
* For securtiy, an exception will be thrown if `sameSite` is set while using an unsupported version of PHP.
* To use this feature across different PHP versions check the version first. E.g.
* ```php
* [
* 'sameSite' => PHP_VERSION_ID >= 70300 ? yii\web\Cookie::SAME_SITE_LAX : null,
* ]
* ```
* See https://www.owasp.org/index.php/SameSite for more information about `sameSite`.
*
* @throws InvalidArgumentException if the parameters are incomplete.
* @see https://secure.php.net/manual/en/function.session-set-cookie-params.php
*/
@ -385,7 +395,15 @@ class Session extends Component implements \IteratorAggregate, \ArrayAccess, \Co
{
$data = $this->getCookieParams();
if (isset($data['lifetime'], $data['path'], $data['domain'], $data['secure'], $data['httponly'])) {
session_set_cookie_params($data['lifetime'], $data['path'], $data['domain'], $data['secure'], $data['httponly']);
if (PHP_VERSION_ID >= 70300) {
session_set_cookie_params($data);
} else {
if (!empty($data['sameSite'])) {
throw new InvalidConfigException('sameSite cookie is not supported by PHP versions < 7.3.0 (set it to null in this environment)');
}
session_set_cookie_params($data['lifetime'], $data['path'], $data['domain'], $data['secure'], $data['httponly']);
}
} else {
throw new InvalidArgumentException('Please make sure cookieParams contains these elements: lifetime, path, domain, secure and httponly.');
}

Loading…
Cancel
Save