While working on this article, I received a Security bulletin highlighting a critical flaw in phpBB. This is a fairly mature open source forum written in PHP, and one that’s had its fair share of critical flaws. The fact that there are still more being found, and more likely to be found, shows you how difficult it is to write completely secure software, even for an experienced team of developers.
Ensure your software is up to date
It seems obvious, but many installations still contain old versions of PHP, with known exploits. By keeping up-to-date with security bulletins (for example from Security Tracker) you’ll be informed when an exploit is discovered, and be able to take action, hopefully before the exploit is used against you. Exploits can be for PHP itself, other applications on your servers such as MySQL or Apache, or, more commonly, PHP applications, such as phpBB.
Register Globals
Any article on security has to start with the register_globals setting in your PHP configuration. Until version 4.2.0, this setting was on by default, and most applications were written with the assumption that the setting was on. Even now, many versions later, many administrators still change the setting back to on to allow legacy applications to work painlessly. Some high profile applications, such as OSCommerce (as of June, 2005) still only work with register_globals on.
register_globals being on is a gaping wide hole of a security risk. It allows users to set global variables inside a script from by passing them from outside (usually the GET or POST method). Since a feature of PHP is that variables don’t need to be initialized, they rarely are, and this lapse allows the attacker to do so on your behalf. It is possible to code securely with register_globals on, it just makes the task that much more difficult, and the risks much greater. Here’s an example of some exploitable pseudocode:
<?php // example1.php if (some or other condition) { $authenticate = 1; } // if ($authenticate == 1) { // allow access to something important } ?>
What’s wrong with the above? If register_globals is on, a malicious users can pass a parameter, as follows:
www.example.co.za/example.php?authenticate=1.
Since the variable $authenticate was never initialized, the user gains access where they shouldn’t. Here’s how the code can be secured.
www.example.co.za/example.php?authenticate=1.
Since the variable $authenticate was never initialized, the user gains access where they shouldn’t. Here’s how the code can be secured.
<?php
// example2.php
// first initialize the authentication variable
$authenticate = 0;
if (some or other condition) {
$authenticate = 1;
}
//
if ($authenticate == 1) {
// allow access to something important
}
?>
However, by simply having register_globals off, the first script would also be immune from that sort of attack. A script called from the URL above would not run with $authenticate set to 1 in the global namespace. Rather, the variable would only be accessible as $_GET[‘authenticate’], where it can do much less harm.
Include files and the web tree
Include files are often used to store passwords and other confidential data. When stored in the web tree there’s a circular round of problems. If they have the extension .inc, poorly configured Apache webservers will allow the the file to display as plain text. For example, www.example.co.za/conf.inc could display a database username and password. You can (and always should) configure Apache to bar the display of .inc files. However, you can’t always assume this will be case in the particular environment where your code is deployed. It’s also not always directly under the control of the programmer, and relies upon the system administrator. Many applications now use the .php extension to pre-empt this, or .inc.php. The files should now never be displayed in plain text. At the very least PHP will interpret the file and return a blank page. However, include files with a .php extension have also been exploited before. They’re not meant to be points of entry, and this means that they aren’t always checked thoroughly. It’s best practice to put include files outside of the web tree. Ideally, any file that’s not meant to be a point of entry (such as libraries and includes) should sit outside the web tree.