PHP 5 Security Techniques
- Remembering the Basics
- Validating Form Data
- Using PECL Filter
- Authentication with PEAR Auth
- Using MCrypt
With more and more personal information being stored on the Web—credit card data, social security numbers, maiden names, favorite pets—today's PHP developer cannot afford to be ignorant when it comes to security. Sadly, most beginning programmers fail to understand the truth about security: there is no such thing as "secure" or "insecure." The wise programmer knows that the real question is how secure a site is. Once any piece of data is stored in a database, in a text file, or on a Post-it note in your office, its security is compromised. The focus in this chapter is therefore how to make your applications more secure.
This chapter will begin by rehashing the fundamentals of secure PHP programming. These are the basic things that I hope/assume you're already doing. After that a quick example shows ways to validate different kinds of data that might come from an HTML form. The third topic is the new-to-PHP 5 PECL library called Filter. Its usage isn't very programmer-friendly, but the way it wraps all of the customary data filtering and sanitizing methods into one interface makes it worth knowing. After that, two different uses of the PEAR Auth package show an alternative way to implement authorization in your Web applications. The chapter will conclude with coverage of the MCrypt library, demonstrating how to encrypt and decrypt data.
Remembering the Basics
Before getting into demonstrations of more particular security techniques, I want to take a moment to go over the basics: those fundamental rules that every PHP programmer should abide by all of the time.
To ensure a basic level of security
Do not rely upon register_globals.
The advent of register_globals once made PHP so easy to use, while also making it less secure (convenience often weakens security). The recommendation is to program as if register_globals is off. This is particularly important because register_globals will likely disappear in future versions of PHP.
Initialize variables prior to using them.
If register_globals is still enabled—even if you aren't using them—a malicious user could use holes created by noninitialized variables to hack your system. For example:
if (condition) { $auth = TRUE; }
If $auth is not preset to FALSE prior to this code, then a user could easily make themselves authorized by passing $_GET['auth'], $_POST['auth'], or $_COOKIE['auth'] to this script.Verify and purify all incoming data.
How you verify and purify the data depends greatly upon the type of data. You'll see many different techniques in this chapter and the book.
Be careful if you use variables for included files.
If your code does something like
require($page);
then you should either make sure that $page does not come from an outside source (like $_GET) or, if it does, that you've made certain that it has an appropriate value. See the technique in Chapter 2, "Developing Web Applications."
Be extra, extra careful when using any function that runs commands on the server.
This includes eval(), exec(), system(), passthru(), popen(), and the backticks (``). Because each of these runs commands on the server itself, they should never be used casually. And if you must use a variable as part of the command to execute, perform any and all security checks on that variable first. Also use the escapeshellarg() and escapeshellcmd() functions as an extra precaution.
Consider changing the default session directory or using a database to store session data.
An example as to how you would do this is discussed in Chapter 3, "Advanced Database Concepts."
Do not use browser-supplied filenames for storing uploaded files on the server.
When you move a file onto your server, rename it to something safe, preferably something not guessable.
Watch for HTML (and more important, JavaScript) in submitted data if it will be redisplayed in a Web page.
Use the strip_tags() or similar functions to clear HTML and potential JavaScript from submitted text.
Do not reveal PHP errors on live sites.
One of the most common ways to hack a site is to try to "break" it—do something unexpected to cause errors—in the hopes that the errors reveal important behind-the-scenes information.
Nullify the possibility of SQL injection attacks.
Use a language-specific database escaping function, like mysqli_real_escape_data(), to ensure that submitted values will not break your queries.
Program with error reporting on its highest level.
While not strictly a security issue, programming with error reporting on its highest level can often show potential holes in your code.
Never keep phpinfo() scripts on the server.
Although vital for developing and debugging PHP applications, phpinfo() scripts reveal too much information and are too easily found if left on a live site.