Using PHP to ensure website security
PHP is the most commonly used server-side programming language. 81.8% of web servers deploy it, and it's the default option for many web developers. The most popular CMS options are built on PHP platforms, including WordPress, Magento, Joomla, OpenCart, and Drupal. If you're looking for a development language to get into, PHP should be considered an extremely valid option.
PHP is a beautiful language. It's one of my favorites to use and the possibilities feel limitless. These possibilities come with drawbacks, though. One of the main problems with PHP is that it isn't guaranteed to be secure. That part is up to you. In this article, we're going to discuss a few of your options for ensuring website security in your PHP-based site.
The basics of PHP security vulnerabilities
PHP is a weakly typed language. This means that PHP will automatically convert data of an incorrect type to the type that is expected. There are many different reasons that this is a disadvantage and many different ways that this can be exploited. PHP is more than just a language, it is a web framework in addition. Built upon this are a vast array of libraries that contribute to the language. These libraries may be secure or cripplingly insecure depending on the source and last update. When you're considering your PHP application, you have to take all of this into consideration – the language, the framework, and the libraries used.
PHP errors could be another source of vulnerability. PHP handles errors by throwing a notice, but the faulty code continues running. If you do not have your error handling turned on at all, you may go months without realizing that your hand-crafted code was full of security holes and bugs. This is a terrifying prospect, to say the least. Naturally, the best way to counteract this is to turn error reporting on as high as it can go.
<?php error_reporting( E_ALL ); ?>
The PHP framework could also present problems that could pose a huge threat to the security of your website. One possible example of this is that PHP files are stored in publicly accessible folders. It is relatively easy to find the filepath of a config file if you know how to look. Once someone finds a file on your site that looks tempting, it's all too easy to make use of the content help within. PHP's framework is also lacking protection against CSRF. Because PHP was designed to be easy-to-use, many people are building websites without realizing that they need this mechanism.
When it comes to PHP libraries provided by third party vendors, it should take a lot of scrutiny in order to actually allow it to be deployed on your website. The security issues lie in more than just hashed commands and functions, but also the writing of the developers on the project. Poor development is easy game for the right intruder, and you need to be wholly aware of the security risks and vulnerabilities that may be included with what you're installing.
Where to begin locking down
Upgrade PHP. Now. Go. Upgrade it now, keep it upgraded, and do not let yourself fall behind. This is an extremely important aspect of PHP security and any CMS residing on a PHP platform. Everyone should know that an up-to-date WordPress installation is a secure WordPress installation. The same goes for PHP. Don't be misled, for the time being you should stay away from the Beta installs, as these are still in testing mode. Granted, they've learned from the security flaws of past releases and sometimes may be even more secure than the current version. This doesn't mean that these releases are flawless, though.
Configuring PHP correctly can also contribute greatly to the security of your site. PHP's website provides some thorough instructions for this on their website, here. One of the important portions of a properly configured website is the php.ini file. The file is read at run time and will initiate the settings declared within. These directives include the maximum execution time for a script to run, whether to track errors, and output buffering, to name a few. You can always find the latest php.ini file in PHP's git repository.
Let's be honest, PHP handles uploads in a less than graceful manner. If you have improperly scripted PHP handling file uploads, you may find yourself in a world of hurt. For instance, the common way of checking a file is to check the type. This is obviously not the best way to ensure the security of your website, as the header information for a file can be doctored. While checking for the mime type can be server-intensive, it also ensures a better option. This is not perfect, but it is certainly better than checking only the file type.
One of the best and easiest ways to check the mime type is to use the Fileinfo class. As of PHP 5.3, this class is included in your install.
Problems with variables
There are a lot of different problems with user submitted or editable variables. Using $_GET variables with variables that should be kept private is astoundingly foolish. These variables are an addition to the path of the file using them. These variables may be read, edited, or simply excluded by anyone with proper access. If you aren't error handling correctly, than a missing variable could expose bugs in your code and a potential door for intruders.
Let's take the following example as a case study for GET variables. We'll say that you use a simple URL in your emails that directs potential customers to your page. In the URL that you send out, there is a GET variable with their first name. You print this unsanitized variable on that page with a welcome message. It feels like a great way to make a potential customer feel at home, right? Well, almost.
Let's say that someone looking to defame your company gets wind of this. They set up an automated mailer that looks like it's sending from your company. They take that URL you're sending visitors to and change the first name GET variable to 'Scumbag'. Now, that potential client opens up your page and sees the “Welcome, Scumbag!” message. Suddenly, this message isn't as welcoming as it used to be, is it?
<script>alert("We are now legally required to inform our customers that our products have been proven to cause cancer in several case studies.")</script>
Suddenly, it isn't an arguable point, is it? Just clean your variables.
In addition to these prankster type of cracks, there's also a good amount of script injection vulnerabilities with GET variables. Let's say that you've decided instead to pass the customer's identification number in that URL. You query your local database and grab the safe and secure first name there instead of the vulnerable GET variable name. This would be a much better idea as long as you remember to clean your variables.
Script injection is a terrifying technique where your entire database could be compromised if you don't sanitize your variables correctly. If a user simply adds a double quote to that variable, it ends the SQL query and an error is returned tot he page. This within itself isn't bad, what's bad is that it's easy to add to this closure of the SQL argument and add another. Your entire database could be wiped out simply because you didn't spend a few extra minutes writing a sanitation function. So how are you to ensure that your variables are clean and expected?
By default, submitted variables aren't cleaned with PHP. Even employing simple tactics like addslashes() doesn't do everything that you need. To program around this used to take a fair amount of difficult programming including Regular Expressions and validation. Luckily, the newly available filter_var() function helps you to do this quickly and easily. You can use this function on variables held in GET, POST, and COOKIE. This isn't the only function you should be using to sanitize your variables, but it does does a lot of work out of verification.
You should also remember to add slashes to your variables in order to prevent script injection. There's also the technique of ensuring that the variable you're passing through your scripts is exactly what you expect it to be. It is good practice to use === instead of == to make sure that you're getting exactly what you expect. There are also a number of functions you can use that are appropriate to certain circumstances. One of these functions is htmlspecialchars(). This function will turn all of the special characters submitted through a form and convert them to their appropriate character entities.
In addition to making sure that all of your POST and GET variables are cleaned, I must warn you about the REQUEST. Using the $_REQUEST super global is strongly discouraged in code. This will search POST, GET, and COOKIE data for a matching key. This could cause many problems do to variables with the same name held in different places. It could also cause confusion for you and other developers working with your code. Developing clean, clear, and concise code should be your top priority. The use of this super global will hinder that goal greatly.
Authentication doesn't involve a preexisting PHP function that you can just run whenever you need to ensure a user is who they say they are. If there's ever a session hijack, it's up to you as the programmer to find it and prevent it with your code. Think of your website as a quiet, dusty town that doesn't need to lock their doors. The reason they don't need to lock their doors is because of the vigilance of the security force employed by that town. You are in charge of creating and programming that ever-vigilant security force. In order to keep your website up and running properly, that security must be ready and watching.
Sessions IDs are considered private data. There should never be a circumstance where you have to print the session's ID in any way to the user. It is also considered good practice to bind sessions with IP addresses. That way, if the IP address of the session changes, you can detect a session being hijacked and prevent it. You should also make sure that the session is deleted completely. Be sure to unset your cookies as well as the session storage. Always make sure that your sessions expire as well as timeout after a period of no activity.
Fixing problems before they're problems
In short, you should make sure that you're using the proper programming techniques in order to ensure a secure PHP website. If you realize that you've made a mistake somewhere on a project, I highly encourage you to go back and rectify it before it becomes a huge problem. There are many different problems that can happen with your website if you let them go unchecked. Even a low-risk hack can be embarrassing and devastating to your reputation.
Let's go out there and make some websites that we can be proud of. Let's do our work properly and completely. We are the ones building the way that the internet looks and feels, let's not drop the ball!