|
Posted by Gordon Burditt on 03/11/07 04:14
>> When the session handler "open" routine is called, session_id()
>> returns the session ID the browser supplied if there was one,
>> otherwise it returns an empty string. The documentation says this
>> but not specifically about what happens when it's called from the
>> session handler open routine.
>
>session_id() returns the empty string before session_start(), and the
>session value after session_start() has been called, so this function
>is not useful to test for an existing session created at login.
But I'm not looking at it BEFORE or AFTER session_start(), I'm
looking at it DURING. Specifically, when the session save handler
open() routine is called (while session_start() is running). THEN,
it appears to be usable to tell whether a session is going to be
created.
>> So, if session_id() returns a non-empty string, and
>> that session doesn't exist in current sessions, you have
>> (1) A session-fixation attempt,
>> or
>> (2) A user returning after their session has expired (or they logged
>> out explicitly) and been deleted.
>> Either way, there is no existing session data, so they can't be logged in.
>> I propose setting a global variable like $possible_session_fixation_attempt
>> to either 0 or 1 depending on the results of this check.
>>
>> If the user tries to go anywhere but the login page, he's not logged
>> in, so he'll be redirected to the login page. At the login page,
>> if $possible_session_fixation_attempt is set, call
>> session_regenerate_id(true). The argument causes the deletion of
>> the old session. Then proceed with the normal logic for the login
>> page. The logged-in session will have the new session id.
>>
>> Now, this idea doesn't prevent (or attempt to prevent) hijacking
>> of unexpired sessons due to snooping or extremely lucky guessing
>> or the user publishing the session ID. It does prevent tricking a
>> user into using a pre-determined session ID, which can then be
>> trivially guessed.
>
>I don't understand this last sentence. Session IDs are always created by
>the server. The browser cannont force the server to create an arbitrary
>session with an arbitrary value.
The browser usually can make the server create an arbitrary session
with a user-specified *ID*. This is called session fixation, and
what I'm trying to prevent. The contents of the $_SESSION variable
may not be specified, or sessions would be completely hopeless for
security.
In the existing setup, pretty much every page calling session_start(),
all that is necessary for creating a session with an ID that I, the
user, specify, is to create a cookie in my browser and make a HTTP
request of the server. This is really easy with things like CURL.
It gets worse. With trans_sid set, the user can ask for:
http://www.example.com/dir/foo.php?PHPSESSID=00000000000000000000000000000000
Now, this isn't absolutely horrible security, because there's no session
file for this, so it starts off fresh with no session variables set.
That's why existing pages check for $_SESSION['user'] or something.
They may also need to have that variable anyway: many pages need to
know which user is logged in to display user-specific information.
The bad part comes when you trick another user into forcing a session day
which you, the bad guy, can guess easily because YOU set it.
Note that for some applications, setting up a session for anyone, no
login required, is desirable behavior for, say, multi-page surveys to
pass information between the pages of the survey. The login model is
not the only use for sessions, although it is a very common one.
[Back to original message]
|