In the previous post, we looked at ways that an attacker can impersonate an authorized user and thereby gain unauthorized privilege escalation. Beyond credential capture, it is possible for an attacker to exploit the session maintenance mechanism itself in order to participate surreptitiously in a session for which an authorized user has provided legitimate authentication credentials. That is, it is possible for an attacker to "hijack" the session.How does this happen? Most web applications, including PHP web applications, are built around the hypertext transfer protocol (HTTP). HTTP is a stateless protocol, meaning that each protocol request and response pair is independent of the others. That is, by default, sequences of related HTTP requests and responses are not grouped together into sessions, with an associated session context. This functionality is a bedrock necessity for many web applications, but it is functionality that is added above and beyond the basic protocol.
Of course, PHP implements session management functionality. If you use PHP's native session mechanism, the requests and responses are grouped together using a PHP session identifier (
PHPSESSID). When you call session_start, PHP checks for a PHPSESSID variable in the incoming cookie or query string. If PHPSESSID exists, the _SESSION superglobal is populated from the associated session store. Otherwise, PHPSESSID is given a value and a new session store is initialized.If an attacker can guess the value of the generated
PHPSESSID, she can participate in the session. For example, if a particular session has a session variable $_SESSION['authenticated'] set to TRUE, the attacker may be able to interact with the PHP application as an authenticated user. Thankfully, PHP generates values for PHPSESSID that are sufficiently random so that simple guessing is impractical. The remaining options for an attacker are: to set the session identifier to a desired value, or to capture the current session identifier.Setting the session identifier to a desired value can be as simple for the attacker as having the victim click on a link like the following:
<a href="http://valuableapp.com/index.php?PHPSESSID=1234">Click Here</a>That is, if no PHP session has been initiated for a particular user at a particular site, the attacker can specify the PHP session identifier by specifying the
PHPSESSID in a cookie or the query string. This behavior is clearly not desirable. How can it be prevented? Session fixation attacks (as such attacks are known) cannot be prevented per se without modifying PHP's default session management behavior. However, judicious use of session_regenerate_id can make the attack impractical.First note that attacker knowledge of the session identifier isn't (or rather, shouldn't be) particularly problematic until the legitimate user authenticates. Consequently, regenerating the session identifier following each authentication and/or privilege escalation should be sufficient to prevent impersonation. The following code illustrates:
There remains the risk of session identifier capture. The
$_SESSION['authenticated'] = FALSE;
if (authenticate_user())
{
session_regenerate_id();
$_SESSION['authenticated'] = TRUE;
}
PHPSESSID variable should be propagated between requests using a cookie. The risk of cookie data exposure can be reduced by following the golden rules, and using SSL encryption. A useful additional anti-impersonation measure is to store the HTTP_USER_AGENT value (or, rather, a hash thereof) in the _SESSION superglobal and require reauthentication should it change during the session.Image credit: Aquila