session_start() issues regarding illegal characters, empty session ID and failed session
The problem:
session_start()
relies on $_COOKIE[session_name()]
, so, if you edit the cookie value to something like #$#$FDSFSR#"#"$"#$"
or simply empty it (not delete the cookie) and refresh a page with your code:
if (!session_id()) {
session_start();
}
The following warning is generated:
PHP Warning: session_start(): The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in /home/username/public_html/session_start.php on line 7
This happens because php
is checking if session_id()
exists and, in fact, it exists, but contains illegal characters not allowed as session_id
name.
A valid session id
may contain only digits, letters A to Z (both upper and lower case), comma and dash ([-,a-zA-Z0-9]
) between 1 and 128 characters.
My solution:
Check if $_COOKIE[session_name()]
is set and contains a valid session_id
prior to session_start()
, otherwise, delete the session cookie and only then session_start()
, something like:
function safeSession() {
if (isset($_COOKIE[session_name()]) AND preg_match('/^[-,a-zA-Z0-9]{1,128}$/', $_COOKIE[session_name()])) {
session_start();
} elseif (isset($_COOKIE[session_name()])) {
unset($_COOKIE[session_name()]);
session_start();
} else {
session_start();
}
}
start the session:
safeSession();
NOTES:
1 - session_name
is defined on your php.ini
as session.name = SOMETHING
(default is PHPSESSID
), so, you may be looking for a cookie matching session.name
. You can use the session_name()
function to retrieve it.
2 - Session cookie manipulation can be used by hackers to dump information from your server (username
and path
) if ini_set('display_errors', 1);
is set.
3 - session_regenerate_id(true)
works but, because it checks the current session_id
prior to assign a new one, generates warnings.
4 - I've tested the code with several invalid session names and no errors or warnings were generated, everything worked and intended.
References:
session.c Source Code
My bet would be, you were under attack at this time. This means someone manipulated your session cookie for example.
Since session_start();
is a system function, I don't think it would generate invalid ids.
In my opinion, option 2 is the best. But if I remember correct, you need to set a custom error handler for this.
This answer seems better for me:
$ok = @session_start();
if(!$ok){
//Hello Hacker ;)
session_regenerate_id(true); // replace the Session ID
session_start();
}