From f1e14f9e1290b0d766c271f906d04366a2cd78c3 Mon Sep 17 00:00:00 2001 From: Jorg Sowa Date: Sun, 3 May 2026 14:48:39 +0200 Subject: [PATCH] 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 --- NEWS | 3 +++ UPGRADING | 18 ++++++++++++++++++ ext/session/session.c | 6 +++--- php.ini-development | 9 ++++----- php.ini-production | 9 ++++----- 5 files changed, 32 insertions(+), 13 deletions(-) diff --git a/NEWS b/NEWS index 5453a5fc094f..749b303c3339 100644 --- a/NEWS +++ b/NEWS @@ -136,6 +136,9 @@ PHP NEWS - Session: . Fixed bug 71162 (updateTimestamp never called when session data is empty). (Girgias) + . Changed defaults of session.use_strict_mode (now 1), session.cookie_httponly + (now 1) and session.cookie_samesite (now "Lax") to provide secure session + behavior out of the box. (RFC: Secure Session Configuration Defaults) - Soap: . Soap::__setCookie() when cookie name is a digit is now not stored and diff --git a/UPGRADING b/UPGRADING index e55e03be48b9..c433498f76b7 100644 --- a/UPGRADING +++ b/UPGRADING @@ -75,6 +75,24 @@ PHP 8.6 UPGRADE NOTES comparison. Custom session handlers that rely on write() being called with empty data (e.g. to destroy the session) should implement the same logic in their updateTimestamp() method. + . The defaults of three session INI settings have changed to provide secure + behavior out of the box: + - session.use_strict_mode is now 1 (was 0). Strict mode rejects + uninitialized session IDs, mitigating session fixation. Custom session + handlers that previously relied on accepting externally supplied IDs + without a corresponding storage entry must either implement + validateId() / create_sid() or explicitly set this to 0. + - session.cookie_httponly is now 1 (was 0). Session cookies are no + longer accessible to JavaScript via document.cookie. Applications + that read the session cookie from JavaScript must explicitly set + this to 0. + - session.cookie_samesite is now "Lax" (was unset). Session cookies + are no longer sent on cross-site requests other than top-level + navigations using safe HTTP methods. Applications that depend on + session cookies being sent on cross-site POST submissions must + explicitly set this to "None" (and also set session.cookie_secure + to 1). + RFC: https://wiki.php.net/rfc/session_security_defaults - SPL: . SplFileObject::next() now advances the stream when no prior current() diff --git a/ext/session/session.c b/ext/session/session.c index 0a6ad38e5581..24c296f83227 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -923,11 +923,11 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("session.cookie_domain", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_domain, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.cookie_partitioned", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_partitioned, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionSameSite, cookie_samesite, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.cookie_httponly", "1", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cookie_samesite", "Lax", PHP_INI_ALL, OnUpdateSessionSameSite, cookie_samesite, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateUseOnlyCookies, use_only_cookies, php_ps_globals, ps_globals) - STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals) + STD_PHP_INI_BOOLEAN("session.use_strict_mode", "1", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.referer_check", "", PHP_INI_ALL, OnUpdateRefererCheck, extern_referer_chk, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.cache_limiter", "nocache", PHP_INI_ALL, OnUpdateSessionStr, cache_limiter, php_ps_globals, ps_globals) STD_PHP_INI_ENTRY("session.cache_expire", "180", PHP_INI_ALL, OnUpdateSessionLong, cache_expire, php_ps_globals, ps_globals) diff --git a/php.ini-development b/php.ini-development index ee75459ea56c..78ae50708d5a 100644 --- a/php.ini-development +++ b/php.ini-development @@ -1305,10 +1305,9 @@ session.save_handler = files ; Strict session mode does not accept an uninitialized session ID, and ; regenerates the session ID if the browser sends an uninitialized session ID. ; Strict mode protects applications from session fixation via a session adoption -; vulnerability. It is disabled by default for maximum compatibility, but -; enabling it is encouraged. +; vulnerability. ; https://wiki.php.net/rfc/strict_sessions -session.use_strict_mode = 0 +session.use_strict_mode = 1 ; Whether to use cookies. ; https://php.net/session.use-cookies @@ -1350,13 +1349,13 @@ session.cookie_domain = ; Whether or not to add the httpOnly flag to the cookie, which makes it ; inaccessible to browser scripting languages such as JavaScript. ; https://php.net/session.cookie-httponly -session.cookie_httponly = +session.cookie_httponly = 1 ; Add SameSite attribute to cookie to help mitigate Cross-Site Request Forgery (CSRF/XSRF) ; Current valid values are "Strict", "Lax" or "None". When using "None", ; make sure to include the quotes, as `none` is interpreted like `false` in ini files. ; https://tools.ietf.org/html/draft-west-first-party-cookies-07 -session.cookie_samesite = +session.cookie_samesite = "Lax" ; Handler used to serialize data. php is the standard serializer of PHP. ; https://php.net/session.serialize-handler diff --git a/php.ini-production b/php.ini-production index b10e2ba9944a..eb6880fe75d6 100644 --- a/php.ini-production +++ b/php.ini-production @@ -1307,10 +1307,9 @@ session.save_handler = files ; Strict session mode does not accept an uninitialized session ID, and ; regenerates the session ID if the browser sends an uninitialized session ID. ; Strict mode protects applications from session fixation via a session adoption -; vulnerability. It is disabled by default for maximum compatibility, but -; enabling it is encouraged. +; vulnerability. ; https://wiki.php.net/rfc/strict_sessions -session.use_strict_mode = 0 +session.use_strict_mode = 1 ; Whether to use cookies. ; https://php.net/session.use-cookies @@ -1352,13 +1351,13 @@ session.cookie_domain = ; Whether or not to add the httpOnly flag to the cookie, which makes it ; inaccessible to browser scripting languages such as JavaScript. ; https://php.net/session.cookie-httponly -session.cookie_httponly = +session.cookie_httponly = 1 ; Add SameSite attribute to cookie to help mitigate Cross-Site Request Forgery (CSRF/XSRF) ; Current valid values are "Strict", "Lax" or "None". When using "None", ; make sure to include the quotes, as `none` is interpreted like `false` in ini files. ; https://tools.ietf.org/html/draft-west-first-party-cookies-07 -session.cookie_samesite = +session.cookie_samesite = "Lax" ; Handler used to serialize data. php is the standard serializer of PHP. ; https://php.net/session.serialize-handler