When websites consisted of static html pages created offline and uploaded by the marketing department, protecting a corporate site from hackers involved little more than backing up the files offline and ensuring the ftp password for uploading new files didn't fall into the wrong hands.
But the growth in popularity of server-side scripting languages such as PHP means much of the html content displayed by web browsers is now dynamically generated, and many sites contain no static html files at all.
Consequently, website security is no longer a simple matter of keeping backups and ensuring a few passwords are changed regularly. Instead, server-side programs must be designed from the ground up to be hack-proof and, just as importantly, hacker-evident.
So here are some tips on how to ensure that PHP applications, and the SQL databases that often power them, remain impenetrable to hackers.
Hide database passwords
Do not include confidential information in PHP files because hackers sometimes manage to exploit a bug in PHP code or in the server's configuration that allows them to view the source code directly.
The most common type of confidential information found in PHP files are the passwords required to access a MySQL server or similar database. By placing these in a .inc file, which is in a non-web-accessible directory, (that is above the web server's docroot), you minimise the damage that can be caused if a hacker views the PHP source code in his web browser.
Use the require_once command to include the file. And give the file a .inc.php extension – rather than merely .inc – in case the server doesn't have a default handler specified for .inc files and thus displays them to casual surfers as if they were .txt or .htm files.
Hide FTP password caches
Ensure your development directory tree doesn't include any ftp password cache files, as hackers often use Google to search for these and crack their contents. A popular culprit is ws_ftp.ini files, which are easy to locate via a simple web search and use very weak encryption on their stored passwords. Such files should remain on your development machine and never be uploaded to the server.
Turn off register_globals
Ensure that register_globals is turned off in your installation of PHP. This prevents hackers from being able to set the value of a variable in your code by simply entering the data into a field on an html form of their creation and submitting it to your site.
Register_globals is off by default in PHP 4.2 and above, but many developers turn it on because it makes for easier coding.
Turn on error reporting
Make it a habit to start all your PHP programs with an error_reporting (E_ALL) command. This will ensure that you receive warnings about null variables and all other errors in your code. Before accessing a variable that might have a null value, use the isset() function to ensure that it actually exists.
If you use open-source PHP programs, such as content management systems, keep a regular watch on the application's official website to ensure you are aware of any security fixes that are released.
You should never modify the source code of any open-source application you use, because applying patches or upgrading to new versions becomes difficult. If you modify any templates, log your amendments in case a new version of the software uses different templates.
Test with GWA
Google's new Web Accelerator, which speeds up users' web surfing by pre-fetching the files referenced within the current page, breaks many CMSes because, as soon as the CMS loads the Welcome page, it pre-fetches the page that is mentioned in the log-off link and thus logs off the user. Expect patches for this problem from the makers of most applications soon.
Test your own applications with GWA and, if necessary, include html code in your dynamically generated pages to instruct GWA not to pre-fetch anything. A web search for Google Web Accelerator will show you how.
Log, log, log
In addition to the logs produced by your web server, include some logging functions in your code so that, for example, all actions are written to a database or text file on the server along with the user's IP address.
Use $_SERVER["REMOTE_ADDR"] to get the user's IP address. You can then use the gethostbyaddr() function to look up its DNS entry. Also check out $_SERVER["HTTP_CLIENT_IP"], which sometimes contains the client's real IP address rather than the one belonging to their ISP's proxy server.
Check login status frequently
If your application requires a user to log in before they can access a specific set of pages or functions, check their login status before every action. Don't assume that, because they were logged in when they viewed the admin menu, they are still logged in when they access a submenu from this page.
They might well have typed in the URL of the submenu directly in their browser, rather than arriving there from the expected route.
Protect your admin functions
Avoid writing applications that contain both user-level and admin functionality, unless you are confident it is not obvious to casual users how to access the admin functions. Don't store admin code in an /admin directory below your application, for example, as hackers will try that first.
Keep the admin url secret, rather than having a "admin users click here" link on the public site, even if it leads to a password request, because hackers can then use programs to fire thousands of guesses at your app every minute.
If you are using an off-the-shelf application, such as Drupal, Mambo or phpBB, ensure you change all the default passwords and remove the installation files as soon as the software is installed. And if you have to weaken permissions on any config file in order to tweak it, replace the permissions as soon as you're done.