2015-09-29
A Case Study in How NOT To Process Orders
Home »Linux/BSD»PHP Security
2015-09-29
A Case Study in How NOT To Process Orders
2014-02-08
Reading email SMTP headers to trace the origin of the message.
2014-02-07
Rants about the pains of performing what should be a simple package upgrade.
Your IP address is
3.238.253.163
Before you start reading this, please note that it was originally written in 2004, and things have moved on quite a bit since then. It was written as a posting to a hosting forum, and wasn't really intended to be a complete 'article' as such. The 'sorry it had to be mentioned' comment about REGISTER_GLOBALS relates to the fact that my host at the time didn't want to turn them off.
Update in 2020: This page is really not worth reading if you're running PHP 7, and most of it doesn't really apply to PHP 5, either. You should probably stop reading and move along.
Brilliant article about writing secure PHP code: http://www.devshed.com/c/a/PHP/PHP-Security-Mistakes/
Other points I would add to it:
When you need a directory to accept uploads from the public, add some .htaccess directives to prevent the execution of PHP, PERL, coldfusion, ASP, etc scripts and pages, otherwise you may be allowing an attacker to upload their own PHP scripts, which may include some commands you wouldn't like, such as unlink(), and shell_exec(). You might also like to run a cron job to delete any files which don't match the type you are expecting to appear in a directory (eg - delete anything in /var/www/html/avatars/ which isn't *.jpg, *.gif or *.png)
Don't keep old copies of scripts lying around in public folders. You may have index.php (your main page), and something like index.php.old, or index.php.bak. Attackers know to look for .old, and .bak extensions on ASP, CFM, PHP, etc scripts, as they will be shown in plain text, giving them a glimpse at your source (allowing them to identify any further holes you've left open), and possibly giving away the username and password for your database server (if you've put mysql commands in there).
Often, you'll keep the sql username and password in a different file, which is either included or required by the main script. Don't name these files connect.inc, or indeed anything .inc, as .inc files will also be shown in plain text, giving away their contents. Instead, use .inc.php (which will be executed rather than simply displayed), and, if you can, keep all your include files in a separate directory, protected by .htaccess passwords.
If you really *must* name your include files something.inc, you might like to add a handler to a .htaccess file so that all your .inc files will be processed as PHP scripts, even when called directly.
Turn register_globals OFF. (sorry, it had to be mentioned) Some older scripts will still need it turned on, and you can turn it on or off in a .htaccess file, by adding a line like this:
, although it's usually configured in your PHP.ini file.
For security reasons, register_globals defaults to OFF in PHP installations after 4.2.0, and you can find good examples of how it gets exploited at http://www.php.net/release_4_1_0.php and http://www.phpbuilder.com/manual/sec...terglobals.php, and a good article about coding with register_globals OFF at http://www.phpe.net/articles/192.shtml
Use MD5. If you run your own authentication system (ie - users need to login before they can access parts of your site), store their passwords as an MD5 hash, this way, even if somebody does get access to your database, they'll only get the MD5 hash of the passwords, not the plaintext passwords themselves. This isn't entirely foolproof, as attackers may subject the passwords to brute-force or dictionary attacks, but it makes life much harder for them, than if they just had the passwords. Sometimes I create three password fields for each user, password, pass, and passwd. Only one of them stores the md5 hash for the real password, the others are hashes of randomly generated words. When logging in, if the user tries to authenticate with one of the random strings, I know somebody's been trying to crack passwords, and the account gets blocked/suspended. A bit of overkill, perhaps, but one tries one's best...
Try to avoid "remember me" next time features if you have especially sensitive data, or for accounts with higher system privs. This sort of thing is generally accomplished by storing their user data in a cookie, and if that cookie is copied elsewhere (mischievous coworker/sibling, accidentally shared on kazaa, etc), the account is compromised. It doesn't matter so much if it just means that your flatmate starts posting gibberish to a webforum using your identity, but when he/she starts ordering gay porn with your paypal account, the joke wears thinner and thinner until your girlfriend leaves you and HM Customs and Excise get involved.
Remove sample pages. If you setup a new apache/IIS server, of if you install a new copy of nuke or e107 or some popular script like that, it pays to remove any "welcome" messages or sample pages included with it. Attackers will scour search engines looking for the text of these sample pages, as it indicates a new, out-of-the-box and probably unpatched and untweaked server with all the defaults still in place. They don't have anything personal against bunnyrabbitspicnic.com, it just happens to be running a version of Nuke with a bug in it, so they can deface it and give shouts to all their script-kiddy buddies.
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.0 UK: England & Wales License.
Design by GetTemplate