The most common session attack, session hijacking, refers to all attacks that attempt to gain access to another user's session.
As with session fixation, if your session mechanism only consists of session_start(), you are in hot water, although it isn't as simple. Rather than focusing on how to keep the session identifier from being captured, we focus on complicating the session capture. The goal is to complicate impersonation, since every complication increases security. To do this, we examine what we need to do to successfully hijack a session. In each scenario we will assume that the session identifier has been compromised.
It is not smart to rely on anything at the TCP/IP level, such as an IP address, because these are lower level protocols that are not intended to accommodate activities taking place at the HTTP level. A single user can potentially have a different
IP address for each request, and multiple users can potentially have the same IP address.
Only the Host header is required by HTTP/1.1, so it seems silly to rely on anything else. However, consistency is really all we need, because we're only interested in complicating impersonation without causing trouble for our real users.
Imagine that the previous request is followed by a request with a different User-Agent:
Now an attacker must not only present a valid session identifier, but also the proper User-Agent header associated with the session. This complicates things slightly, which is good for security.
Is there a way to improve on this? We know that the most common way to obtain cookie values is by exploiting a vulnerable browser such as Internet Explorer. These exploits involve the victim visiting the attacker's site, so the attacker will be able to
obtain the correct User-Agent header. Something additional is necessary to protect against this situation.
Imagine if we required the user to pass the MD5 of the User-Agent in each request. An attacker could no longer just recreate the headers that the victim's requests contain, but it would also be necessary to pass this extra bit of information. While guessing
the construction of this particular token isn't too difficult, we can complicate such guesswork by simply adding an extra bit of randomness to the way we construct the token: