Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

PHP applications have a reputation for higher than average security problems. What configuration techniques do you use for making sure the application is secure as possible?

I'm looking for ideas like:

I normally use Linux, but feel free to suggest Windows solutions too.

share|improve this question
add comment

8 Answers

up vote 14 down vote accepted
  1. Use the open_basedir directive to confine your PHP scripts to their home directory and eventual extra application directories. This is very efficient by itself.

  2. Use hardened php because that costs nothing and it can help.

  3. Use suPHP to have PHP scripts execute as the owner of the file (one user per website) and avoid using files with bad permissions such as 777... suPHP can also allow you to have on php.ini per website so that one site's stupid requirement don't destroy everything.

  4. Mod_security is a big plus but needs to be well used and configured.

share|improve this answer
    
Some bad sites actually need register_globals and fopen so that's why you use a php.ini per site with suPHP. One site can just go kamikaze and the others be (almost) perfectly safe. –  Antoine Benkemoun Jun 6 '09 at 9:50
4  
If they use register_globals and fopen, it suggests the quality is so bad you may want to reconsider using them :) –  David Pashley Jun 6 '09 at 14:57
    
If they're paying 150€/mo, you don't reconsider. –  Antoine Benkemoun Jun 7 '09 at 9:34
add comment

In my experience, most vulnerabilities on a PHP-based web site are the result of poor (site) design, rather than flaws in PHP itself.

Some quick tips:

  • Universally filter input, escape output. Clarificaiton: filter doesn't mean escape, it means "if I find something fishy in this user input, cause the submission to fail and tell the user to reformat."
  • Rather than using escapeshellcmd(), simply don't allow any user input to be executed in the shell. That's dangerous and probably never actually necessary.
  • Don't call functions like phpinfo() on a production site (or if you do, see below*).
  • When designing a web application, always consider "is this a possible attack vector?" Say, SQL injection. If the answer is "yes," plug it immediately--don't say "ok, I'll add that later in development as a feature." Security is never a feature.
  • Never output raw errors to the user; this means setting php.ini's display_errors = Off, log_errors = On. Trap run-time errors and output something pretty. Take Twitter's whale as an example: it won't give the user debug-level information, it just says "woops, something broke, please refresh".

*You might also take a peek at a short post I wrote called "Securing phpinfo(), sort of" and be sure to read the comments http://egovsergo.com/2009/04/03/protecting-your-phpinfo/ It was a quick idea I had to (somewhat) protect phpinfo() if I somehow forgot to remove it on a production site.

In a more general way, some developers write wrappers for sensitive functions which check whether not the "production site" flag is set or not, and disables the sensitive function in production.

share|improve this answer
    
My question was more about how to protect your server against badly written PHP. :) I didn't mean that PHP itself was insecure, more that it attracts less experienced developers and the standard library requires them to remember to protect every call, rather than the library protecting all users. +1 as it's a very useful answer. –  David Pashley Jun 7 '09 at 22:04
    
I got that impression and replied accordingly :) Thanks for the comment! I can't get into it all here, obviously, but those are some big pits. If you have more specific questions, you can surely pose them on Stack Overflow and I and everyone else will contribute. (And for what it's worth, I'm a ZCE). –  msanford Jun 8 '09 at 3:44
add comment

Other parameters that should be altered to harden the PHP:

safe_mode = Off
register_globals = Off
expose_php = Off
allow_url_fopen = Off
allow_url_include = Off
log_errors = On
error_log = /var/log/phperror.log
display_errors = Off
enable_dl = Off
disable_functions="popen,exec,system,passthru,proc_open,shell_exec,show_source,phpinfo"

Store all PHP errors in file /var/log/phperror.log:

touch /var/log/phperror.log
chmod 666 /var/log/phperror.log
share|improve this answer
add comment

I've added the dotdeb repositories to my /etc/apt/sources.lst

deb http://packages.dotdeb.org stable all
deb-src http://packages.dotdeb.org stable all

As they patch php / apache / mysql much more frequently than Debian does.

share|improve this answer
add comment

Consider setting up open_basedir on a "per site" basis. open_basedir is a php.ini setting which will prevent your scripts from accessing files outside of a defined white list. If your server hosts several sites, it'll prevent one site from reading the database settings from another site. It'll also prevent a php script from accessing/modifying core system files. Open basedir is easy to set up, just add the line "php_admin_value open_basedir /my/list/of/folders:/as/a/colon/seperated/list" to each Apache vhost.

Also consider turning off the PHP script engine for all sites/folders which shouldn't contain PHP scripts (e.g. an uploaded images folder). Again, this is simple, add "php_admin_value engine off" to any Apache VirtualHosts not needing php. To disable PHP in a directory, put the same thing into a Directory tag.

Run file permissions as tight as possible, avoid write access to PHP scripts for the Apache user, this prevents a running script from modifying itself or other scripts on the same site/server. Avoid 777 permissions if at all possible, figure out the minimum permissions required to run the application and use those.

If you're hosting multiple sites, each with their own database, use a seperate MySQL/Postgres user for each, and set permissions on each user such that they only have access to the relevant databases. Again this will prevent a rogue script from tampering with another application's database.

Suosin, HardenedPHP, mod_security and the like are all valuable as well, but use them in addition to a tightly locked down configuration, not instead of.

share|improve this answer
add comment

Suhosin has a rather substantial performance cost, so the "costs nothing" comment is a bit off.

share|improve this answer
2  
What good is a fast, hacked website? :) hardened-php.net/suhosin/benchmark.html suggests 8.85% slower on one benchmark. That may be acceptable for the security benefits it provides. This probably should have been a comment rather than an answer. –  David Pashley Jun 6 '09 at 16:13
    
Suhosin protects primarily against local attacks. So, if you share your server with people you don't trust, it may be worth the slowdown. If you have your own server, or your own vm slice, I don't see the point. –  Tom Jun 7 '09 at 1:10
add comment

Are you looking for some basic firewall/topology suggestions? I like the idea of using things like pound to prevent access directly to the PHP webserver from the unwashed internets. That way you can also segregate the webserver from other parts of your network as well.

share|improve this answer
    
No, I'm looking for ways to improve the security of the PHP runtime. –  David Pashley Jun 6 '09 at 20:45
add comment

Using Suhosin/mod_security/SuPHP certainly will turn your PHP server secure. Disabling certain functions like exec, passthru, system and escapeshellcmd will help a lot too.

share|improve this answer
1  
Isn't escapeshellcmd() just used to escape string? It doesn't provide any way to exec a process. How could someone use it to cause a problem? –  David Pashley Jun 7 '09 at 6:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.