Secure PHP Website
Wow. The question is where to start and how to finish this instructive article. Okay, I will take a deep breath and make an attempt to cover many important concepts about PHP Security. Although there are many factors to consider, I always believe that reading about this subject from credible authors is a good place to start.
Books like ‘Essential PHP Security’ and ‘Pro PHP Security’ will give you some insight into security and they could even help more experienced programmers catch something they may have missed. Although the internet is a great place to solve a problem, reading is an excellent source to discover beneficial learning that you may not be looking for.
Although I will get around to making standard security methods for PHP scripts, the first two details I will cover are making a secure connection and making your server more secure. If you don’t protect your access to the server and you don’t make your server a safe place to operate, you could be in for problems.
PHP Security From Source To End
When you build a website, you more than likely use a PC and host the website on a remote server. This means the traffic route will go from your pc to your router. After that, your ISP routes the request to your web host. Your web host could have a hop or two as well. Whether you use FTP, SFTP, http or SSH, your data will travel over this Internet highway.
Although this might not seem like securing PHP, the connection process is extremely important because your local network could be attacked and exposing passwords; which could inevitably give someone access to the server. Passwords on the network could be snatched with Wireshark or some other tool. Protocols like FTP and SSH will give yourself away. If you want to connect remotely, SSH, SSL and SFTP should be practiced for remote logins. In addition to that, Ethernet is more secure than Wireless.
PHP and The Web Server
PHP is a package that is installed on Linux. By default, it is very insecure. If you rent a VPS or dedicated server, you will more than like need to make adjustments so that you have better security. On shared hosting, you will have a configuration that you cannot change, unless your ISP makes special rules for your own account.
Dangerous PHP Functions
PHP has quite an array of functions that can create havoc. Some of these functions allow for direct access to the server. This means, a skilled Linux admin could do anything from blast email spam to adding, editing or deleting any file on your server. In other words, the user could have full control of your machine.
So, if you have a poorly configured server, any client with access to an account like Cpanel or FTP could add PHP files that can run databases and modify files. From a security point of view, you do not want that, unless the server is your own and you have no intention of anybody else being able to access the file system.
So, how do you make things safer for all users? You can customize any account so that they can only use PHP functions that will not cause problems. Alternatively, you can create custom php.ini files and add them into the public_html folders.
With PHP Suhosin, you can make sure users cannot use a php.ini file in their public_html folder to override the one you want them to use. In addition to keeping a tight grip on the PHP functions, you can monitor the php.ini file for all users and other php files to see if any changes and undesirable files are showing up on the server.
If you not allow anyone access to the public_html folders, a custom php.ini files in the public_html folder will only make login sessions available within the same folder.
The code below shows some functions which can be quite dangerous. This lines of code can be used with the Linux command line to find some nasty functions. If you find some files on your system with these functions, you may want to look into why they are they there and consider getting rid of them asap.
root# grep -RPn “(passthru|shell_exec|system|phpinfo|base64_decode|chmod|mkdir|fopen|fclose|readfile|php_uname|eval|tcpflood|udpflood|edoced_46esab) *\(” /home/username/public_html
root# grep -RPn “(passthru|shell_exec|system|phpinfo|base64_decode|chmod|mkdir|fopen|fclose|readfile|php_uname|eval|tcpflood|udpflood|edoced_46esab)” /home/username/public_html
root# grep -RPn “(passthru|shell_exec|system|base64_decode|chmod|mkdir|readfile|php_uname|eval|tcpflood|udpflood|edoced_46esab) *\(” /home/username/public_html
PHP File Handlers
When PHP runs on the server, it uses a filehandler like suPHP, CGI, and fastCGI. If you happen to use Web Host manager, you can see your list of PHP handlers at Service Configuration >Configure PHP and suEXEC >PHP 5 Handler. You have selections in the dropdown list. If you want one that is not there, you can install and enable it with easy Apache.
For most situations, suPHP and fcgi(fast CGI) are good options and arev very popular.
For many web hosting environments, this is the default setting. It is a very good handler that does not consume excessive memory. However, it has 1 security drawback since it allows every account to make custom php.ini files. in other words, any domain name on your server can create this file and enable any php function they want. In most cases, you don’t want this to happen, unless nobody has access to all files on the server.
Luckily, you do have the option to edit the ‘/opt/suphp/etc/suphp.conf’ file on the server to make sure nobody can create and use custom php.ini files.
To disable the ability to create custom php.ini files, change the following lines of code in the suphp.conf file that are located directly below ‘[phprc_paths]’.
;application/x-httpd-php=/usr/local/lib/ ;application/x-httpd-php4=/usr/local/php4/lib/ ;application/x-httpd-php5=/usr/local/lib/ ##change to application/x-httpd-php=/usr/local/lib/ application/x-httpd-php4=/usr/local/php4/lib/ application/x-httpd-php5=/usr/local/lib/
Now, save the file and restart Apache. Now, you can test custom php.ini files and should see that they do not work. If you use Varnish, you need to restart that service too so that the cache does not pull a cached file.
Fast CGI is a PHP handler that makes it easier to customize any account or domain since you can use the php.ini sections [PATH=] and [HOST=] within the default php.ini file. FastCGI can be added with Easy Apache using Web Host Manager, or via the Linux command line. To install and build with easy Apache, go to Web Host manager and Select Easyapache >Start based on profile >Next step >Next step >Exhaustive options list >Select Mod FastCGI >Save and Build.
To use these directives, you add the sections at the end of the files and make specific rules; like the example below.
[PATH=/home/username/public_html] suhosin.executor.func.blacklist="eval,gzinflate,system,proc_open,popen,show_source,symlink,safe_mode,allow_url_fopen,base64_decode" #disable_functions="eval,gzinflate,system,proc_open,popen,show_source,symlink,safe_mode,allow_url_fopen,base64_decode"
In addition to using FASTCGI, you can install the PHP security extention called suhosin. You can install via the command line with ‘yum install php-suhosin‘ or add it with Easy Apache in Web Host Manager.
With suhosin, you can add various other settings to your custom php.ini file. An example is shown above. As you can see, there is more than one method to blacklist various php functions. The user at /home/username/public_html with use these functions while other users would use other specified blacklisted php functions. This method gives complete control over each account.
Suhosin allows many more customizable features than without. For example, if you use [HOST=] or [PATH=] sections you are limited to ‘PHP_INI_SYSTEM’. You can find a full list of directives at http://www.php.net/manual/en/ini.list.php.
As an alternative to the blacklist above, you could have whitelist functions using ‘suhosin.executor.func.whitelist’.
If you want to switch from FASTCGI to suPHP, you always disable and enable the FASTCGI module using the examples below.
sudo a2enmod fastcgi sudo a2dismod fastcgi
File uploading with PHP can be very useful, but, you want to make sure to only accept the proper mime type and file extension. Otherwise, it can be exploited and you could end up letting a malicious user upload nasty kiddie scripts to your website. Often, these uploaded PHP or Perl scripts use some of those functions that can do damage when they are allowed access in the wrong hands.
Unfortunately, there are many tutorials and even bestselling books with upload code that is very insecure. Although these scripts can help learn how things work, a stronger programmer could easily exploit this weakness. One possible ugly scenario could be a situation where a malicious user uploads a PHP file with a shell script that lists all your files and folders on your system. At this point, he could plant files for spamming, grabbing your database and downloading your files. When the user has your files….trouble.
If you ever have this happen to you, you want to back everything up, find and delete the nasty files. Often, the files show up at the same time since the user had a session where he was on some mission.
After you back up and delete the files, you want to change all passwords and keep tightening everything up. Make sure your system runs safely and prevent the attack from happening again. If you find files that have security issues, fix them.
The register_global directives should be off. If is off by default with PHP 5.3 and lower and it had been removed with PHP 5.4. Why is it so bad? It allows you to set variables in the url.
An example is shown below that creates two variables and two values. One variable is called $name and it has a value of ‘filename’ while the other one is called $owner and it has a value of ‘jack’. You could also make a variable equal to true with a url string like authorized=1.
Although using register_globals=on is bad practice, you could always make sure variables set in the url string are invalid; then reclare them and use stronger checking that makes sure these new variables are invalid.
The example below the checks for a variable’s existence. The insecure if statement just does something if the variable exists. Meanwhile, the other block removes any value given to the variable and make sure it comes from a post request. Now, the url string that set values would not have an impact in the script; even with global_variables = on since the variable values in the string would be removed and the $_GET string would not meet the posted criteria.
// do this
Securing with Unset() Function
// do this
Securing With An Array
$name = array();
$name[‘name’] = $_POST[‘name’];
Sanitize User Input
Although this line is used by every tutorial going, I will use it anyway…”Never trust user input’. When you program PHP, forms and user input will be something that you will probably work with on a regular basis. The absolute basics are to sanitize user input with htmlentities(htmlspecialchars) or mysql_real_escape_string.
To sanitize a string for XSS by adding html entities into the string,
$var_sanitized = htmlentities($_POST[‘variable’], ENT_QUOTES);
$var = $_POST[‘variable’]);
$sanitized_var = filter_var($var, FILTER_SANITIZE_SPECIAL_CHARS);
To sanitize a string for mySQL and prevent SQL injection,
$password = mysql_real_escape_string($_POST[‘password’]);
Although Varnish is not typically included in your typical PHP security lecture, it really does wonders for session based PHP content. If Varnish is enabled on a website, the administrator logins will be useless because it will deliver the page from the cache and it will ignore any session. To use Varnish with sessions you need to unset variables and learn to edit the varnish configuration file. Since varnish does not cache files with SSL, you can have a secure login with SSL and a non-working login with non-https pages.
Don’t Show Directory Lists
There really is not much use in showing files within a directory. If you do not show the list of files, they cannot be downloaded and users cannot snoop around. A simple line in your htaccess file will prevent this from happening.
# Prevent Directory listings
Don’t Make Enemies
With so much social interaction going around, you would be surprised where hackers and crackers could be found. They could be someone you had offended at a web hosting company, competition, or a social media stage like LinkedIn and Twitter. Knowing they are out there can help in your eliminiating any potential hangups. But, if you offend a hacker, you could cause an action against your own network. It is best not to ruffle any feathers out there.
Passwords and Publc Computers
Although it is alarming and disturbing to know other people or coworkers will try to snoop your private passwords, you may want to make sure you never use them on a public or work computer. The computer could have software that records typed text. In addition to that, some browsers like Firefox store passwords in plain text. So, you might think that logging into your https site is secure, meanwhile, your manager may go look in your cookies and find you password. Then, it could be used on another computer or to check your other logins.
The moral of the story here is to never allow any user access to your passwords. If you have to use a public computer, never save the password for future logins.