Honor session.use_strict_mode for the built-in SessionHandler - #23071
Honor session.use_strict_mode for the built-in SessionHandler#23071iliaal wants to merge 1 commit into
Conversation
SessionHandler does not expose validateId(), so strict mode fell back to php_session_validate_sid() and accepted unknown IDs. Delegate validation for exact SessionHandler instances to the wrapped module. Keep the historical behavior for subclasses, which may implement custom storage. Closes phpGH-23071
eeb4cf1 to
36d134d
Compare
Girgias
left a comment
There was a problem hiding this comment.
The methods should just be implemented on the class. Rather than this nonsense.
|
This would be automatically fixed in PHP 9 thanks to the deprecation (if it passes) https://wiki.php.net/rfc/deprecations_php_8_6#deprecate_passing_a_sessionhandler_object_to_session_set_save_handler_which_does_not_contain_the_create_sid_and_validateid_methods |
SessionHandler exposes no validateId(), so registering it leaves ps_validate_sid undefined and PS_VALIDATE_SID_FUNC(user) falls through to php_session_validate_sid(), which reports every id as existing. With session.use_strict_mode=1, the new default, an attacker supplied id is adopted rather than regenerated. Implement validateId() alongside the other methods that delegate to the wrapped module. A subclass that overrides open() without calling parent::open() never opened that module, so it cannot answer for the id and keeps its previous behavior. Closes phpGH-23071
36d134d to
e13ba93
Compare
|
Done in e13ba93. One guard was needed to get there: a subclass that overrides open() without calling parent::open() never opened the module it would validate against, so it returns true rather than vetoing the id. Without that, session_set_save_handler_class_002.phpt and _016.phpt lose their session data, since those subclasses replace storage and inherit the method. |
|
A deprecation would not change the 8.6 behavior though, the id is still adopted. Does it cover |
SessionHandler implements neither SessionUpdateTimestampHandlerInterface nor a validateId() method, so registering it leaves ps_validate_sid undefined and PS_VALIDATE_SID_FUNC(user) falls through to php_session_validate_sid, which reports every id as existing. With
session.use_strict_mode=1, the new default in 8.6,session_set_save_handler(new SessionHandler, true)adopts an attacker-supplied id instead of regenerating it.validateId() is now implemented on the class alongside the other methods that delegate to the wrapped module. A subclass that overrides open() without calling parent::open() never opened that module, so it cannot answer for the id and returns true, which keeps the behavior those handlers have today.