From the discussion of user management, cookies, and sessions in Chapter 19, "Cookies and Sessions," you learned that there was more to effective and secure session management than just making calls to the session_start function. In particular, we face a number of security concerns when working with sessions, and some configuration options that we will want to make sure we have set properly. ConfigurationAs discussed in Chapter 19, php.ini has a number of configuration options for sessions in PHP to control the exact functionality. For our web application samples, we use the following settings:
The one configuration option not mentioned in the preceding list is the session.gc_maxlifetime value, which defaults to an extremely short 1,440 seconds (24 minutes). The exact value we will use for this depends on what sort of web application we are writing. For an E-Commerce store where we are dealing with sensitive information, we will want to keep this to a still reasonably short value, perhaps 3,600 seconds (1 hour), whereas for something a little less sensitive, such as a message board or web log system, we could let this be something much larger, such as 86,400 (1 day). We can either change the value of session.gc_maxlifetime in the php.ini files we use for each application, or we can use the ini_set function in your scripts before we call the session_start function. SecurityTo provide more optional security for users and web applications, we will do a little bit more than just call session_start at the top of each script. As shown in Chapter 19, we are particularly worried about two aspects of session security: session fixation (how hackers attempt to determine a user's session ID) and minimizing damage after a session is compromised. We try to minimize session fixation by using the following code to create our sessions: session_start(); /** * Try to prevent session fixation by ensuring that we created * the session ID. */ if (!isset($_SESSION['created'])) { session_regenerate_id(); $_SESSION['created'] = TRUE; } We will try to more closely associate the user with his session ID by using the User-Agent string from the HTTP request, as follows: define('USER_AGENT_SALT', 'PosterStore'); /** * Try to limit the damage from a compromised session ID by * saving a hash of the User-Agent: string with another * value. */ if (!isset($_SESSION['user_agent'])) { /** * create a hash user agent and a string to store in session * data. */ $_SESSION['user_agent'] = md5($_SERVER['HTTP_USER_AGENT'] . USER_AGENT_SALT); } else { /** * verify that the user agent matches the session data */ if ($_SESSION['user_agent'] != md5($_SERVER['HTTP_USER_AGENT'] . USER_AGENT_SALT)) { /** * Possible Security Violation. Tell the user what * happened and refuse to continue. */ throw new SessionCompromisedException(); } } Putting It All TogetherAfter we have configured php.ini, we can write a session.inc file that we will include at the top of any of our scripts that require sessions. This file performs the three critical tasks of (last-minute) configuration, session initialization, and worrying about security. The complete contents of the version we will use for one of our samples are as follows: <?php /** * session.inc * * Author: Marc Wandschneider * * This file will contain the core session handling code that * we will use in our poster store web application. We will * do a few extra things when we create a session to try to * avoid some common security problems: * * 1. We will add a 'created' variable to the session data to * verify that we were the ones who created this session. * (This helps avoid session fixation attacks.) * * 2. We will record a hash of the client's USER_AGENT string * along with another string to reduce the chance of a * compromised session ID being used successfully. */ define('USER_AGENT_SALT', 'PosterStore'); /** * One of these sessions can last 60 minutes */ ini_set('session.gc_maxlifetime', 3600); session_start(); /** * Try to prevent session fixation by ensuring that we created * the session ID. */ if (!isset($_SESSION['created'])) { session_regenerate_id(); $_SESSION['created'] = TRUE; } /** * Try to limit the damage from a compromised session ID by * saving a hash of the User-Agent: string with another * value. */ if (!isset($_SESSION['user_agent'])) { /** * create a hash user agent and a string to store in session * data. */ $_SESSION['user_agent'] = md5($_SERVER['HTTP_USER_AGENT'] . USER_AGENT_SALT); } else { /** * verify that the user agent matches the session data. */ if ($_SESSION['user_agent'] != md5($_SERVER['HTTP_USER_AGENT'] . USER_AGENT_SALT)) { /** * Possible Security Violation. Tell the user what * happened and refuse to continue. */ throw new SessionCompromisedException(); } } ?> |