You are here: Re: Session fixation idea « PHP Programming Language « IT news, forums, messages
Re: Session fixation idea

Posted by Umberto Salsi on 03/10/07 23:04

gordonb.ka1po@burditt.org (Gordon Burditt) wrote:

> I had this idea about preventing session fixation, and I'm wondering
> what anyone else thinks about it. The idea is, essentially, don't
> allow session ids that YOUR PHP didn't generate (and aren't yet
> expired) to log in. That way if someone sticks a made-up session
> ID on a URL, it won't matter, unless it happens to correspond to
> an active session (guessing a user password is probably easier).

This is problem I had already considered. With the current design of the
'session' extension, the function session_start() actually has two
roles:

1. If the browser does not sent a cookie, or the sent cookie is not valid
or expired or does not match any of the existing session files, a new
session is created with an empty $_SESSION[] array.

2. If the cookie returned from the browser match an existing session file,
the session is renewed (the same cookie is sent back to the browser).

Unfortunately this design has two drawbacks:

a. Entropy waste and possible security issue. Commonly, programmers call
session_start() in every page of their WEB site. A malicious remote user can
then repeatedly call any one of these pages so forcing the server exhaust
its entropy reserve, and the less secure pseudo-random number generator is
used instead.

b. The programmer needs to add an element to the $_SESSION[] array in
order to check for a valid login session. Typically this element is the
user name $_SESSION['user'] or the primary key that identify this user
$_SESSION['user_pk'] or simply a flag $_SESSION['logged_in'].

In my opinion, two functions should be introduced in place of session_start():
session_new() and session_exists().

session_new() create a new empty session and send the corresponding cookie to
the browser. This function must be called only after the user has successfully
logged-in. The implementation is really simple:

/*. void .*/ function session_new()
{
session_destroy();
$_SESSION = array();
session_start();
}

session_exists() return FALSE if the browser does not sent a valid
session cookie, otherwise this function renew the session calling
session_start(), then return TRUE. This is the function that must be
used in every page of the WEB site (apart the login page). If the session
exists, the code of the page can be executed, otherwise the browser
should be redirected to the login page:

<?php // some_page.php
if( ! session_exists() ){
header("http://www.mysite.xxx/login.php");
exit;
}

// rest of the page here:
header("Content-Type: text/html; charset=utf-8");
// etc. etc.
?>

Note that the program does not need to check for the existence of the
$_SESSION['user'] or $_SESSION['user_pk'] elements, since if the session
exists it was certainly created by our program at the time of the login.
The implementation of the function session_exists() can be as follow:

/*. boolean .*/ function session_exists()
{
$sn = session_name();
if( ! isset( $_COOKIE[$sn] ) )
# No cookie from client.
return FALSE;
$sv = (string) $_COOKIE[$sn];
if( preg_match('/^[-,a-zA-Z0-9]+$/', $sv) !== 1 )
# Not a valid cookie syntax.
return FALSE;
$sf = session_save_path() ."/sess_". $sv;
if( ! file_exists($sf) )
# This cookie is not a session or session expired.
return FALSE;
session_start(); # restore session.
if( session_id() === $sv )
# The restored session is that we actually expected.
return TRUE;
# Race condition detected: the old session $sv expired
# in the meanwhile and a new one was created by session_start(),
# so $_SESSION[] is empty. Roll-back and return FALSE.
session_destroy();
return FALSE;
}

> Is this already standard practice, new, or is there something better?
>
> I like to use a session save handler to put the data into a database.
> So in my case, using a session save handler isn't a lot of extra
> work. My approach can deal with sessions saved just about anywhere,
> but you need explicit handlers you can modify to use it.
>
> This approach assumes that you already have a login setup and every
> protected page will check for a logged-in and unexpired session,
> and if not, redirect the browser to the login page. There's some
> session data like $_SESSION['logged_in'] = 1 to indicate a valid
> login. You also have a timeout so the session expires some time
> (say, an hour) after the last click.
>
> 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.

> 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.

Regards,
___
/_|_\ Umberto Salsi
\/_\/ www.icosaedro.it

 

Navigation:

[Reply to this message]


Удаленная работа для программистов  •  Как заработать на Google AdSense  •  England, UK  •  статьи на английском  •  PHP MySQL CMS Apache Oscommerce  •  Online Business Knowledge Base  •  DVD MP3 AVI MP4 players codecs conversion help
Home  •  Search  •  Site Map  •  Set as Homepage  •  Add to Favourites

Copyright © 2005-2006 Powered by Custom PHP Programming

Сайт изготовлен в Студии Валентина Петручека
изготовление и поддержка веб-сайтов, разработка программного обеспечения, поисковая оптимизация