Being a seasoned coder myself (I've been doing PHP coding on and off for 6 years now) I think I can speak with some authority about this subject. I came to believe that PHP is pretty much a Perl copy-cat where they eliminated the features which they considered
too hard for the beginner. While catering for a beginner public is a laudable goal, you must think very, very hard how a feature can be abused, because beginners, exactly because they are beginners, do not have a firm grasp of the side effects of their actions. And many of them fall in the
it works, so everything must be ok trap.
Also for a pretty long time the official PHP documentation contained little information about security. (This is not true any more though. They have an entire chapter about it. Go read it if you haven't done so already. Also they mention security considerations in the documentation of every function where it is the case).
Even so 43% of the bugs found in 2006 were in applications written in PHP. This is pretty staggering when you think about the fact that PHP being a dynamic interpreted language eliminated several large categories of vulnerabilities present in
classical languages: buffer overflows, double frees, format strings, etc. But it bought others: remote file inclusions, SQL injections and cross site scripting. The statistics should worry both the hosting companies and users of products written in PHP and should serve as a wake-up call to the programmers of such systems. Below all a bunch of tips which should help somewhat in securing the servers / applications, but they are not 100% effective (then again, nothing is).
- The most important one (although all of them are important): turn off allow_url_fopen and allow_url_include. This is a feature which caused a lot of security problems and I suspect that the only reason for its existence that it's a cool programming abstraction (wow I can tread local and remote files in the same way!). However I claim that this is used by less than 0.01% of all the projects out there and yet if haunts all of them. You can disable these functions server wide (if you own the server) or on a per-directory basis (see the corresponding manual page if you're running Apache)
- Turn register globals off if you haven't done so already. This is pretty much turned off on all current installations of PHP (since off is the default since version 4.3.0), but you can never know. Avoid software which claims to need this
featureturned on as plaque. I remember that at one point I looked at osCommerce and when I saw that they said something along the lines of
for proper functioning this requires register_globals to be turned on, we're working on the next version which will function with it offI ran like hell (to their defense this was a couple of years back and most probably they fixed the issue)
- Turn magic quotes on if possible. Now this is a little more tricky than the previous two, since this may actually break perfectly secure code. So use it with care and remember that you can turn it off and one on a per directory basis if you're using Apache and PHP as a shared module.
- Turn on safe mode. This again can be a little problematic, because while many big software packages (like Wordpress or phpBB) work flawlessly, most probably you will encounter ones that don't. Also, this setting is global to the whole server, which means that (a) only the sysadmin can set it and (b) all the users must agree.
- If you are using shared hosting, store sessions in the database. The default session handler uses the filesystem to store sessions handles, more precisely the temporary directory which is shared between all the users. This means that others hosting sites on the same server can steal / modify your session data.
- If you are a programmer, read OWASP. Read their top ten problems. Be sure to understand them. Consider using their input filters. Remember however that there is no silver bullet and only though knowledge can you attain true security!
- If you are system administrator, consider deploying Suhosin and / or mod_security. Keep in mind however that deploying these solutions is usually not possible on shared hosting servers, because they almost certainly break some scripts. Their deployment must be a coordinated effort between the application team and the sysadmins.
- If you are currently considering different PHP applications / scripts: look out for the above mentioned signs. If the script author recommends to turn any of those settings on / off, that should be strong sign not to use that script.
- If you are a developer, use prepared statements for you SQL queries. Read this short introduction at SANS to get the basic idea. This is an other idea where PHP is severely lacking. Perl had prepared statements since the early release of the DBI libary in 1991 (that's right, since more than 15 years!). It is very hard not to use prepared statements in Perl. Consider using a database abstraction layer. Know however that Pear::DB does not do proper prepared statements! I don't know about ADOdb.