PHP RFC: Make session_regenerate_id() more secure
Keeping HTTP session as secure as possible is what the session manager's task. Session manager can improve HTTP session security without user code modification while keeping compatibility with existing applications. Please note that this RFC is for session manager behavior.
session_regenerate_id() is used to generate new session ID. It's better to delete old session data to reduce risk of session hijack. However, session_regenerate_id() leave old session data by default currently. (i.e. session_regenerate_id(FALSE) is the default) Old session data is active and usable until GC.
Old session is left active for reliable session ID regeneration. There are many reasons why old session is left. Examples are:
- Browsers connect to web server with multiple connections.
- Mobile network may loose radio, may have hand over, etc.
- Large network providers have multiple gateways for off loading traffic and packets may arrive out of order.
For reliable session ID regeneration, only short periods (few seconds for wired connections, few minutes for mobile connection) is enough.
Leaving old session opens window to attacker widely:
- Old session lives long term and never expires if there is access to it. i.e. Attacker may abuse stolen session forever.
- There is no mechanism to detect possibles attack even if session manager may detect attacks.
Counter measure for session hijack: Requirement - Session ID regeneration must be reliable.
- Make sure old session is deactivated/deleted after certain period.
- Raise error/exception for invalid access. (Raise error for should be deleted session access)
Problem of immediate old session deletion:
- Make session ID regeneration unreliable. (Unacceptable)
- Remove alarm for possible attacks. (No detection = Insecure)
“Make sure old session is deleted certain period” and “Raise error/exception for invalid access” provides much better security than current way or immediate deletion.
Errors may be raised for either legitimate user or attacker. If error is raised for legitimate user, legitimate user could know they are under attack. (Possibly network is dangerous or app has vulnerability) If error is raised for attacker, attacker could know they might be caught by illegal access.
Risk of stolen session
Stealing session ID is easy regardless of HTTPS. Attacker can set up fake router by ARP spoofing. Most networks do not have ARP spoofing prevention, even detection. For HTTP, attacker can view session ID simply. For HTTPS, attacker can set up transparent HTTPS stripping proxy and steal session ID. Most users do not care much if they are connecting via HTTPS or not.
Above attack can be done by existing tools. i.e. Script kiddies' task.
If you are curious, search YouTube or net.
Add __SESSION_REGENERATE_ID_EXPIRE__ time stamp
“Make sure old session is deleted certain period” can be achieved by time stamp in session data. When session_regenerate_id() called, session manager sets
for old session data.
“Raise error/exception for invalid access” can be done when session manager initializes session, check above value. If expired session is accessed, session manager raises “SessionRegenerateIdExpireException”.
NOTE: Since new session_start() accepts any INI values as option, programmers may change INI value by session_start() as follows.
Actual deletion of old session is left for GC. Precise deletion of expired session data will be address by other RFC.
There may developers dislike values in $_SESSION. However, this is convenient for developers to test their applications.
- Test program may set $_SESSION['_SESSION_REGENERATE_ID_EXPIRE_'] as it requires and test application.
Exception may result in fatal error. Therefore, exception would be configurable by INI.
session.regenerate_id_exception=0 or 1 where 0 for 5.x, 1 for 6.x.
Backward Incompatible Changes
- If user script has SESSION_REGENERATE_ID_EXPIRE key in $_SESSION, it may break application.
- Raised exception may break application.
- Test programs could be affected.
Proposed PHP Version(s)
Impact to Existing Extensions
If there are any php.ini settings then list:
- hardcoded default values
- php.ini-development values
- php.ini-production values
- “session.regenerate_id_expire = 180” for all. (180 seconds)
- “session.regenerate_id_exception=0 or 1” where 0 for 5.x, 1 for 6.x.
Make sure there are no open issues when the vote starts!
Unaffected PHP Functionality
Other than session management, there is no affected functionality.
Session expire and GC can be improved by time stamp also.
Proposed Voting Choices
- Add SESSION_REGENERATE_ID_EXPIRE time stamp Yes/No
Patches and Tests
- 2014/03/19 - Add exception option as Stas suggested.
- 2014/03/18 - Change RFC to propose time stamping.
- 2013/10/30 - Added details and message option.
- 2013/10/29 - Created RFC