9 Session Security

In this chapter, we cover session security. We look at what a session variable is and why it is used, then show you how to defend against the three major types of session attacks: hijacking, fixation, and injection.

What is a Session Variable?

HTTP is stateless by design. This has some advantages but leaves us with a major problem when dealing with dynamic Web pages. How do we maintain a user’s identity across multiple pages? How do we pass data from page to page? This is where session variables come in; they enable you to track session information about the user through various pages on your site. PHP sessions are like server-side cookie files. Each one stores variables that are unique to the user request that created it and ideally can be accessed only on subsequent requests from that user. Of course, hackers try to turn this functionality into a vulnerability to gain access to resources. Therefore, there are session attacks that you must attempt to counter.

Major Types of Session Attacks

There are three types of attacks that you need to be wary about when using session variables:

Session fixation

• Session hijacking

• Session poisoning (injection)

Luckily, there are some clear ways to defend against these attacks. It all comes down to session management.

It is also important to note that in a shared server environment anyone with access to the server can access the PHP session files. These people will not be able to identify what Web site each session belongs to, but they can get sensitive information out of the variables. It is very important not to store critical information in session variables because they simply aren’t secure enough to safeguard it. If you have sensitive data that must be passed around your site, store it in the database. This method is slower than storing data in the session, but it is significantly more secure.

Session Fixation

Session fixation is simply a method of obtaining a valid session identifier without the need to predict or capture one. It enables a malicious user to easily impersonate a legitimate user by forcing the session ID. It is the simplest and most effective method for a malicious user to obtain a valid session ID.

The attack itself is very basic. The hacker forms a link or redirect that sends the user to your site with the session ID preset:

<a href=http://YOUR_HOST/index.php?PHPSESSID=1234> Click here </a>

When users click on that link or are redirected there, they connect to your site with a session ID that has been set by the attacker. The attacker can now wait for the users to log in and access your site using their credentials, as shown in Figure 9.1.

Figure 9.1. Diagram of a session fixation attack.

Diagram of a session fixation attack.

PHP has a very good defense for this type of attack in the built-in session_regenerate_id() function. This function generates a new session file for the user, gets rid of the old one, and issues a new session cookie if your site utilizes them. Anytime your users get their credentials challenged, say at login or when they are changing their password, it’s a good idea to run session_regenerate_id. This will greatly mitigate fixation attacks.

Another good tool for dealing with session fixation is to make sure you set a session time-out in the php.ini file. For more information on this, see Chapter 13, “Securing PHP on the Server.”

These methods are not a 100 percent guarantee that an attacker can’t get your users’ session IDs. Hackers could get very lucky and guess a valid ID, or they could snoop it off the network. Guessing isn’t very likely because of the way PHP assigns session IDs. To defend against network snooping, you could use SSL/TSL. This does add a lot of overhead to your site, so you need to determine how secure your site needs to be. You may also want to make sure that you challenge users when they access very sensitive material, or that you do not fully display sensitive data such as credit card numbers.

Session Hijacking

After a successful session fixation attack, a malicious user has your user’s session. What does the attacker do with it? This is where session hijacking comes in. In a hijacking attack, the malicious user tries to access your site utilizing a valid session ID, as shown in Figure 9.2.

Figure 9.2. Diagram of a session hijacking attack.

Diagram of a session hijacking attack.

Obviously the steps we took to defend against fixation will give us some protection, especially regenerating the session ID on a regular basis, but you will still be vulnerable to a sophisticated attack. There are a number of steps we can take to defend against a session hijacking. Some are easily circumvented, and others don’t always allow legitimate users to access your site. You need to weigh security and usability heavily when defending your site. The key is making it very difficult to hijack a user session. There are three common methods for session defense:

• User agent verification

• IP address verification

• Secondary token

User agent verification is a very basic way of verifying the user’s identity. When you create the session ID, you could grab the HTTP_USER_AGENT variable. Then you could verify it on each new page view. Unfortunately, if the session has been hijacked, the malicious agent could have grabbed the user agent info and spoofed it. A better method would be to store the hash of the user agent string. Better yet would be to store the hash plus a seed and verify that. See Chapter 8, “Encryption,” for more information on hashing data. There is another problem with user agent verification; in some specific circumstances the user agent data may not be consistent. Depending on how the user is connected, some proxy servers manipulate the user agent information. For this reason, you may just want to force users to reenter their password if the verification fails as opposed to kicking them out of their session.

IP address verification is very similar to user agent verification. In fact, in some cases it is more secure, as the attacker may know the user agent and be able to spoof the header. You store the users’ IP when you first generate their session, and then on every page load you verify that IP address. There are two major drawbacks to this method. A lot of locations are behind a NAT proxy, so it is possible that the attacker and the user both have the same IP address. The other issue comes from large ISPs like AOL. A number of them, and AOL specifically, have massive proxy setups that send the user out via a different IP address with every page request. If you know where your users are coming from or are willing to set up a different site for AOL users, this method can be very effective. In fact, if your users will be coming from only a small number of IP addresses, this method is great. But generally the drawbacks to IP verification make it unusable.

In token verification, you set up two points of verification. You create a token for the users utilizing a different method from the session ID. When they first log in, create a hash of that token and store it in their session. You can then verify it on every page load. You can also regenerate this token frequently, allowing only a very short window for the attacker to guess it.

None of these methods are foolproof, but all add to your overall security. Having more than one method of verifying your users’ session is always a good idea.

Session Poisoning

This should actually be called session injection, as it is just one more variable injection type of attack. If you allow user input into session variables, make sure you validate the data. Turn register globals off, and see Part III of this book for an in-depth look at dealing with injection attacks.

Patching the Application to Secure the Session

Securing the session capabilities in the application requires two steps:

1. To defeat session hijacking, we implement the secondary token method.

2. To defeat session fixation, we regenerate both the session and the token at crucial points.

Most of the work occurs within the user object, so we’ll start there. First, we rename the $_sessionID private variable to $_tokenID. We will not be storing the actual session ID in the user object but rather the token ID. We also update the _generateSessionID() function to use the token, rather than the session variable. We also rename it to _generateTokenID():

function _generateTokenID() {
                $tokenID = rand(10000, 9999999);

                $dbh = getDatabaseHandle();
                $selected_db = mysql_select_db("guestbook", $dbh);
                $sql = "update Users set tokenID = $tokenID where Username = $username";
                $result = mysql_query($sql, $dbh);
                $success = mysql_affected_rows($dbh);
                if($success == 1) {
                        $cookieName = "guestbook_cookie";
                        $value = $tokenID;
                        $expire = 0;
                        $secure = TRUE;
                        $httponly = TRUE;
                        if(setcookie($cookieName, $value, $expire, "", "", $secure, $httponly)) {
                                return $tokenID;
                        } else {
                                return NULL;
                        }
                }
        }

The code we added is shown in bold. Basically what we’re doing here is creating a token ID and storing it as a cookie in the user’s browser.

Next, we create two token functions, checkToken() and _deleteToken(), as shown here:

        function _deleteToken() {
                if(setcookie("guestbook_cookie", "", time - 3600)) {
                        $this->_tokenID = NULL;
                        return TRUE;
                }
                return FALSE;
        }

        function checkToken() {
                if($_COOKIE['guestbook_cookie'] && $_COOKIE['guestbook_cookie'] == $this->_tokenID) {
                       $this->_generateToken(); // Keep the window of opportunity
                        // as small as possible
                        return TRUE;
                }
                return FALSE;
        }

Finally, we retrofit the login() and logout() functions to create or destroy both the session and the token.

        function login($username, $plaintext_password) {
                $dbh = getDatabaseHandle();
                $selected_db = mysql_select_db("guestbook", $dbh);
                $sql = "select username, password from Users where username = $username";
                $result = mysql_query($sql, $dbh);
                $userinfo = mysql_fetch_array($dbh);
                $salt = createSeed();
                $password = encryptPassword($userinfo['password'], $salt, $plaintext_password);
                if($userinfo['password'] == $password) {        //User is
                        // authenticated
                        $user = new User($username);
                        $user->_tokenID = _generateTokenID();   // Also stores
                        // tokenID in DB
                        session_regenerate_id();
                        return $user;
                } else {
                        return FALSE;
                }
        }

        function logout() {
                // Invalidate both the session and the token
                session_destroy();

                $dbh = getDatabaseHandle();
                $selected_db = mysql_select_db("guestbook", $dbh);

                if(!_deleteToken()) {
                        logError($dbh, "could not delete token cookie", 5);
                }

                $username = $this->_username;
                $sql = "update Users set TokenID = NULL where Username = $username";
               $result = mysql_query($sql, $dbh);
                $success = mysql_affected_rows($dbh);
                return $success;
        }

In the application code, we’ve added code to create the token cookie and start the session before any HTML is sent to the browser. At the end, we invalidate the token cookie and destroy the session. As a final housekeeping task, we’ve changed the sessionID column name to tokenID in the database.

Wrapping It Up

In this chapter, we talked about the three types of session attacks: fixation, hijacking, and poisoning or injection. Session poisoning is just another form of injection attack, which we have covered in quite a bit of depth elsewhere.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset