Skip to content

Commit 27ead91

Browse files
authored
ext/session: secure session configuration defaults (RFC) (#21938)
* ext/session: secure session configuration defaults (PHP 8.6 RFC) Implements the "Secure Session Configuration Defaults" RFC by changing three INI defaults to provide secure session behavior out of the box: - session.use_strict_mode: 0 -> 1 (mitigates session fixation) - session.cookie_httponly: 0 -> 1 (mitigates XSS access to session cookie) - session.cookie_samesite: "" -> "Lax" (mitigates CSRF) RFC: https://wiki.php.net/rfc/session_security_defaults
1 parent 5212b81 commit 27ead91

15 files changed

Lines changed: 48 additions & 20 deletions

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,8 @@ PHP NEWS
156156
(Girgias)
157157
. Null bytes in session.cookie_path, session.cookie_domain, and
158158
session.cache_limiter are now rejected with a warning. (jorgsowa)
159+
. Changed defaults of session.use_strict_mode (now 1), session.cookie_httponly
160+
(now 1) and session.cookie_samesite (now "Lax"). (jorgsowa)
159161

160162
- Soap:
161163
. Soap::__setCookie() when cookie name is a digit is now not stored and

UPGRADING

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,24 @@ PHP 8.6 UPGRADE NOTES
9494
comparison. Custom session handlers that rely on write() being called
9595
with empty data (e.g. to destroy the session) should implement the same
9696
logic in their updateTimestamp() method.
97+
. The defaults of three session INI settings have changed to provide secure
98+
behavior out of the box:
99+
- session.use_strict_mode is now 1 (was 0). Strict mode rejects
100+
uninitialized session IDs, mitigating session fixation. Custom session
101+
handlers that previously relied on accepting externally supplied IDs
102+
without a corresponding storage entry must either implement
103+
validateId() / create_sid() or explicitly set this to 0.
104+
- session.cookie_httponly is now 1 (was 0). Session cookies are no
105+
longer accessible to JavaScript via document.cookie. Applications
106+
that read the session cookie from JavaScript must explicitly set
107+
this to 0.
108+
- session.cookie_samesite is now "Lax" (was unset). Session cookies
109+
are no longer sent on cross-site requests other than top-level
110+
navigations using safe HTTP methods. Applications that depend on
111+
session cookies being sent on cross-site POST submissions must
112+
explicitly set this to "None" (and also set session.cookie_secure
113+
to 1).
114+
RFC: https://wiki.php.net/rfc/session_security_defaults
97115

98116
- SPL:
99117
. SplObjectStorage::getHash() implementations may no longer mutate any

ext/session/session.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -928,11 +928,11 @@ PHP_INI_BEGIN()
928928
STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_domain, php_ps_globals, ps_globals)
929929
STD_PHP_INI_BOOLEAN("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals)
930930
STD_PHP_INI_BOOLEAN("session.cookie_partitioned", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_partitioned, php_ps_globals, ps_globals)
931-
STD_PHP_INI_BOOLEAN("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals)
932-
STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionSameSite, cookie_samesite, php_ps_globals, ps_globals)
931+
STD_PHP_INI_BOOLEAN("session.cookie_httponly", "1", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals)
932+
STD_PHP_INI_ENTRY("session.cookie_samesite", "Lax", PHP_INI_ALL, OnUpdateSessionSameSite, cookie_samesite, php_ps_globals, ps_globals)
933933
STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals)
934934
STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateUseOnlyCookies, use_only_cookies, php_ps_globals, ps_globals)
935-
STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals)
935+
STD_PHP_INI_BOOLEAN("session.use_strict_mode", "1", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals)
936936
STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateRefererCheck, extern_referer_chk, php_ps_globals, ps_globals)
937937
STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateSessionStr, cache_limiter, php_ps_globals, ps_globals)
938938
STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateSessionLong, cache_expire, php_ps_globals, ps_globals)

ext/session/tests/bug74892.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Bug #74892 Url Rewriting (trans_sid) not working on urls that start with #
44
session.use_cookies=0
55
session.use_only_cookies=0
66
session.use_trans_sid=1
7+
session.use_strict_mode=0
78
--EXTENSIONS--
89
session
910
--SKIPIF--

ext/session/tests/bug80774.phpt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22
Bug #80774 (session_name() problem with backslash)
33
--EXTENSIONS--
44
session
5+
--INI--
6+
session.use_strict_mode=0
57
--FILE--
68
<?php
79
session_name("foo\\bar");
810
session_id('12345');
911
session_start();
1012
?>
1113
--EXPECTHEADERS--
12-
Set-Cookie: foo\bar=12345; path=/
14+
Set-Cookie: foo\bar=12345; path=/; HttpOnly; SameSite=Lax
1315
--EXPECT--

ext/session/tests/gh9200.phpt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
GH-9200: setcookie has an obsolete expires date format
33
--INI--
44
session.cookie_lifetime=3600
5+
session.use_strict_mode=0
56
--EXTENSIONS--
67
session
78
--CGI--
@@ -12,7 +13,7 @@ session_id('bar');
1213
session_start();
1314

1415
foreach (headers_list() as $header) {
15-
if (preg_match('/^Set-Cookie: foo=bar; expires=(Mon|Tue|Wed|Thu|Fri|Sat|Sun), [0-9][0-9] (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) 2[0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] GMT; Max-Age=3600; path=\\/$/', $header)) {
16+
if (preg_match('/^Set-Cookie: foo=bar; expires=(Mon|Tue|Wed|Thu|Fri|Sat|Sun), [0-9][0-9] (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) 2[0-9][0-9][0-9] [0-9][0-9]:[0-9][0-9]:[0-9][0-9] GMT; Max-Age=3600; path=\/; HttpOnly; SameSite=Lax$/', $header)) {
1617
echo "Success", PHP_EOL;
1718
exit;
1819
}

ext/session/tests/mod_files/gc_dirdepth2.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ session
77
--INI--
88
session.gc_probability=0
99
session.gc_maxlifetime=10
10+
session.use_strict_mode=0
1011
--FILE--
1112
<?php
1213
$base = __DIR__ . '/gc_dirdepth2_test';

ext/session/tests/mod_files/gc_dirdepth_disabled.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ session
77
--INI--
88
session.gc_probability=0
99
session.gc_maxlifetime=1
10+
session.use_strict_mode=0
1011
--FILE--
1112
<?php
1213

ext/session/tests/mod_files/gc_dirdepth_multi_subdir_count.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ session
77
--INI--
88
session.gc_probability=0
99
session.gc_maxlifetime=10
10+
session.use_strict_mode=0
1011
--FILE--
1112
<?php
1213
$base = __DIR__ . '/gc_multi_subdir_test';

ext/session/tests/mod_files/gc_dirdepth_selective.phpt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ session
77
--INI--
88
session.gc_probability=0
99
session.gc_maxlifetime=10
10+
session.use_strict_mode=0
1011
--FILE--
1112
<?php
1213
$base = __DIR__ . '/gc_selective_test';

0 commit comments

Comments
 (0)