14.2. Session SecurityBecause a session may contain sensitive information, you need to treat the session as a possible security hole. Session security is necessary to create and implement a session. If someone is listening in or snooping on a network, it's possible that he can intercept a session ID and use it to look like he is someone else. It's also possible to access session data from the local filesystem on multiuser systems such as ISP hosting machines. 14.2.1. Session Hijacking and Session FixationSession hijacking is when someone accesses either a client's cookie or session ID, and then attempts to use this data. Session fixation is attempting to set your own session ID. Session fixation and hijacking are easy to combat. We'll make use of the super global variables for the client's IP address and browser type to keep things secure. Example 14-8 demonstrates encoding the information with an md5 function call to thwart these potential security holes. Example 14-8. Checking for session hijacking
When a browser first requests the page in Example 14-8, a session is started. In that session, we stored the encoded combination of the IP address and browser type. That way, when the user returns to this page, we can compare the value stored in the session versus a fresh computation of the IP address and browser type. If the two don't match, we potentially have a hijacker, so we pick a new ID and clear out any saved data for that session. That way, the hijacker cannot retrieve any of the private information stored in the session. This doesn't cause a problem for legitimate users, because they aren't going to change browser or IP addresses in the middle of a session with your web site. Figure 14-9 shows the newly created session the first time the script runs. Figure 14-9. The session is created and validates since it is a new sessionFigure 14-10 shows what happens if the same script is executed again right away from the same browser. Figure 14-10. The session is validFigure 14-11 mixes things up by copying the session ID cookie from the browser in Figure 14-9 and setting Internet Explorer on the same client machine to send a request with the same session ID. Figure 14-11. The browser type change is caughtBecause our script checks the type of browser, and it's changed from Firefox to Internet Explorer, the session is regenerated to prevent a security lapse. 14.2.2. Trusting User DataYou know that trusting data from a user isn't a great idea. But what exactly do you consider to be user data versus system data that you trust?
User input should be checked and escaped properly. Data that's bound for the database must have all special characters such as single and double quotes escaped. If PHP is not running with magic quotes on (discussed later in this chapter), then you'll need to pass user input through addslashes before sending it to the database. Any user input that displays should be checked for embedded HTML that could be used for cross-site scripting attacks. The htmlspecialcharacters function is useful for escaping characters that have special meaning in HTML like less than (<) and greater than (>). 14.2.3. Shared Hosting ConcernsIf you don't have your own dedicated server or are on a server that has multiple users, it can be very dangerous to use the default PHP settings to store your user's session data in a temporary directory. Normally, all users have access to that temporary directory, so they can easily pilfer private data from the session, including the session ID. To make your session data more secure, you can set the session.save_path configuration parameter with the ini_set function to change the path where sessions are stored, as shown in Example 14-9. Make sure that these are stored below the web root directory. Example 14-9. session.save_path functionality
Example 14-9 stores the sessions in the /home/user/sessions directory. Be sure that whichever folder you choose is created and has the correct permissions for the PHP interpreter to write the session data. Typically, this means the file must be writable by the permission group www-data. This folder shouldn't be readable or writable by general users at large. 14.2.4. Preventing Access to the DatabaseThere are a couple of ways to reduce the chance that a malicious user can access your database. First, if there is a problem connecting to the database, the default MySQL error code reveals the location of the databasein other words, the IP address of the host. You'd like to suppress that information. To prevent the standard error message from PHP, add the Error Control Operator, which is the at sign (@), to the front of the database function call. You'll experience a more closed-lipped or dubious error message in Example 14-10 before calling die to stop all processing. Example 14-10. Suppressing the standard database error message
Without the at sign (@) before the function calls, you'll see Figure 14-12. Figure 14-12. The database server's location is revealed in the error messageFrom a security standpoint, notice how little the error message in Figure 14-13 reveals to a potential attacker about the environment. Figure 14-13. We no longer give out more information than is necessaryWhile this may seem like a minor point, minimizing information available to hackers makes getting in much harder, providing you with more security. 14.2.5. Blocking Access to the Database for External HostsIf your MySQL database server is on the same host as the web server, then it makes good sense to block access to the database port for external users. This can be done through the firewall setup utilities that are part of your operating system. The standard TCP/IP port number for MySQL is 3306. The port number is used to differentiate between services on the same host. 14.2.6. Create Separate Database UsersIf you're running more than one application on your server, you should set up separate database users within MySQL for each application. That way, if there is a security breach in one of the applications, the data for the other application wouldn't be compromised. For example, if you have a bookstore web site, you can create all of your database objects to be accessible from a bookstore database account. Another site for employees to check their timesheets could then be set up using a separate database login. Each application continues to work well, and in the event of a security breach, the extent of damage is limited. 14.2.7. Magic QuotesPHP attempts to shield developers from the danger of special characters being used in user input by a process called magic quotes. The escape characters such as single quotes (') and double quotes (") are escaped with slashes (\). By default, any data that comes from GET, POST, and cookies operations is automatically escaped. The escaping process is the same using the addslashes function on a string. When you send data that has special characters escaped to MySQL for insertion, MySQL automatically knows to convert the string back to the original values for storage in the database. While magic quotes are good for beginners, they tend to create as many problems as they solve. Specifically, they waste some processing time, since all input is escaped regardless of whether it is bound for a database or may have been displayed. Example 14-11 shows how magic quotes add an escape character to a value collected from a form. Example 14-11. Seeing the results of magic quotes
The entry in Figure 14-14 returns the screen in Figure 14-15. Figure 14-14. Sending some test data with special charactersFigure 14-15. The string has its special characters escapedAnother annoyance with magic quotes is that you can't always assume magic_quotes are enabled if you're writing PHP code that might end up being installed on a variety of servers. The solution is to check whether it is enabled from within your code and call addslashes manually if it isn't. To check to see whether magic_quotes escaping is active, use the get_magic_quotes_gpc function. Example 14-12 shows how to check for magic quotes and call add_slashes if they are off. Example 14-12. Checking for magic quotes
Again, whether magic quotes are enabled or not, it's up to you to be knowledgeable about how PHP and MySQL treat special characters. Be sure that your site not only works but is secure. We've covered security and numerous issues to help you secure your web site. Next, we'll be discussing validation and error handling. We're very close to creating your blog. How exciting! |