Saturday, June 19, 2010

What is the difference between PHP as an Apache module and as CGI?

SkyHi @ Saturday, June 19, 2010

A computer program is a list of instructions understandable by a computer that allow it to perform a task.

As a simple example, imagine a computer program that reads or receives a block of text, translates all the letters to upper
case, and outputs the result.

There are two ways we could design this program to be run:

We could make it a standalone console program so that we can type its name on the command line and have it convert any text we
give it to upper case. When a standalone program like this is installed on a server, it's sometimes called a
CGI, in a sense, a fancy name for a standalone program.

Or we could incorporate it into another, larger, program while we're building the larger program, so that conversion of text to
upper case becomes one of its built-in features. When a program is turned into a subprogram in this way, it is sometimes said to
be a module of the larger program.

PHP is a program like our upper case conversion program except that it's much
larger and more complicated, but its function is similar. It receives some input text (a PHP script or an HTML file with PHP
instructions embedded in it), and it outputs some result text. The operations that it performs between input and output might be
very simple or very complicated or somewhere in between.

If we're building an installation of the Apache web server,
and we want to be able to use the capabilities of PHP, we can do it either of the two ways:

PHP as Apache module

Apache is designed so that other programs can be incorporated into it as part of itself, and PHP is
designed so that it can be used this way. When the two programs are merged together, the things PHP can do become built-in
features of Apache, and PHP is said to be a module of Apache, or an Apache module. While Apache is processing a file, the execution
PHP code to produce the result text is something that it now inherently knows how to do using only the code that's
been built into it.

PHP as a CGI

Alternatively, we could install the standalone version of PHP on the server, separately from Apache. In this case,
Apache doesn't know how to execute PHP code. However, one computer program can call another program so that it launches and
runs. Apache knows how to call an outside program and receive the output it produces. In this case, Apache doesn't
execute the PHP code itself. Instead, it hands off the file to the PHP interpreter (program). PHP executes the code and sends the
resulting text, if any, back to Apache for further processing and to send to whoever requested it.

Configurability comparison

The main PHP configuration file is called php.ini. On a shared server, the master php.ini file is in a location that is not
accessible by any of the user accounts.

The two different server configurations provide differing options for
whether you can override settings in the master php.ini and whether you can specify equivalent settings in an alternative location.

PHP as Apache module: Because PHP is part of Apache, you can specify some PHP configuration settings in the
.htaccess Apache
configuration file, for Apache to pass through to its PHP module. On a shared server, this usually means that you can override some
of the master php.ini configuration settings in your local .htaccess files.

PHP as CGI: PHP is a completely separate program from Apache, so Apache can't manage the PHP configuration
settings, and you can't set them in .htaccess. On a shared server, if it is not running suPHP to allow users to have an additional
local php.ini file, this may mean that individual users cannot override any PHP settings except for the few that can be set within
a PHP script using
PHP program code.  

Efficiency comparison

PHP as Apache module: PHP is already loaded and ready to run at all times, so this option is faster.

PHP as CGI: The PHP program is read from disk and launched every time Apache needs its services. On a site that uses PHP
at all, PHP usually must be launched and run for every requested page. It is said that
FastCGI can help make PHP as CGI run faster.  

Security comparison

Background: User Permissions

The Linux and Windows operating systems allow for the creation of "users" (human or virtual) on the system. Each user has lists of files and folders that it is
allowed or not allowed to access, and a list of programs that it is allowed or not allowed to run. These access control settings
are called permissions.

You, when you opened an account with your webhost, were assigned a
userID, which is also the system user that you are known as on your Linux server. There are lists of things that you can and
cannot do on the server, and you, your userID, has ownership of all the files you created.

When a program runs on the computer, it runs as though it is one of the system's users (for example, the person who
launched it), and it has the same permissions as that user, the same list of files it can access, and the same list of actions it
is allowed or not allowed to perform.

PHP by default runs as the same user as Apache, which is often the Linux user called "nobody".

Linux does not allow one user to write
into the files owned by another user. You are userID, and PHP is nobody, and therefore by default PHP is unable to write into any
of the files in your website.

That is why, if you need PHP (nobody) to write to your files, you must loosen the permissions to allow other users write access to
your files, by setting the file permissions to 666 and folder permissions to 777.

That can be a security risk because it gives
write access not just to nobody, but also to all the other userIDs on the computer. On a shared server, those are the other user
accounts on the server. Thus, if any account on the server is compromised by a hacker, they may be able to reach across into your
site. Contrary to a common belief, the permissions don't allow "anybody in the world" to write to your files unless they
use some other means to break into the server first. 

A shared server has just one instance of Apache to handle all the accounts (websites). Apache runs continuously and can't be
restarted without causing server downtime, so its userID of "nobody" never changes.

PHP as Apache module: Since PHP is part of Apache,
it launches only once and runs continuously, so there is no opportunity to make it run as any other user. As nobody, it
can't write to your files, so if you need it to do that, you must make the permissions adjustments described above and either
accept the potential security risk or try to find a way to reduce it. One way to reduce it is to make your folders or files
writable by others only for the shortest possible time, when PHP actually needs to do the writing. The rest of the time, keep the
permissions locked down.  

PHP as CGI: Since PHP is freshly launched each time it's needed, there is an opportunity to run it as a different
user with each launch. See the next section.

suPHP provides greater security at a cost of speed

There is an Apache module/program called suPHP, which causes a CGI installation of PHP to run, each time
it is launched, as the user whose account caused it to be launched: your userID.

With this configuration,
PHP runs as you, with the same permissions as you, and is able to write into your files without your having to loosen the
permissions first.

In addition, just like you, it does not have permission to write into anybody else's account on your shared
server, so that if one account on the server is compromised, it does not automatically get access through PHP to other files and
folders in other accounts.

With suPHP, it is also possible for each user on a shared server to have their own php.ini file with PHP
configuration settings to override the ones in the master php.ini.

The downside is that suPHP is slower because it requires the PHP as CGI configuration.

Further reading

  • Discussion of security issues in the PHP Manual.
  • Complete list of php.ini configuration options, and
    table for understanding the locations where each can be
    set (php.ini, .htaccess, etc.).


  1. Sometimes when cleaning up a hacked website, you might run across a file that was installed by the hack and that you can't
    edit or delete. This is usually because the file and/or the folder it is in were created by PHP which was running as nobody.
    That makes nobody the owner. When you are working on your site in control panel or by FTP, you are your userID, not nobody, so
    you are denied access. The solution is to create and run a PHP script that does the editing or deletion. Your PHP script runs
    as nobody, so it is allowed access to the folder and file.

  2. The security advantages of PHP as CGI and suPHP are demonstrated by the April 2010 mass attack on WordPress blogs hosted
    at Network Solutions. In the attack, it appears that a maliciously created hosting account created at Network Solutions was
    able to read the wp-config.php files of other users on the same server. Those files contained in plain text the credentials
    for accessing the MySQL database. That information allowed the hacker to access the databases and inject malicious code.

    The solution was for affected customers to completely wall off their wp-config.php file from other users by setting the
    Linux permissions to 640. This gives read/write permissions
    to the owner, read permissions to the group (irrelevant for our purposes), and NO permissions at all, not even read
    permissions, to other users on the same server. This works because PHP as CGI with suPHP has the same permissions as owner, so
    PHP doesn't need any special permissions other than what the owner already has.

    Contrast that with PHP as Apache module: in order for PHP to read wp-config.php, read permissions must be granted to
    world/other (644). To function properly, WordPress (PHP) must be able to read wp-config.php, but if PHP can read it, so
    can everybody else on the same server because granting permissions to the one automatically grants them to everybody. There is
    no way around this. I've seen a number of suggestions online about how to protect wp-config.php from view, but none of them
    protect against access by a neighbor on the same server, when PHP is configured as Apache module. If Network Solutions had
    been configured this way, this situation would have had no available solution except to get rid of the malicious account
    (which I'm sure they have done) and try to prevent new malicious users from creating new accounts and doing the same thing. In
    other words, not a technological solution but an entirely human one.  

  3. But if #2 above seemed to make the choice look simple, there's a different situation that makes PHP as Apache module look
    good: a Remote File Inclusion is a type of exploit that tricks one of your PHP scripts into fetching script code from a remote
    site and running it. With PHP as CGI, the malicious script has owner-level permissions for every file and folder in your site,
    just like you do, so it can potentially modify every file. But with PHP as Apache module, the malicious script is just nobody,
    like every other PHP script, and is more limited in the amount of damage it can do. It can't put new files in folders unless
    they have 777 permissions, and it can't modify files unless they have 666 permissions.

    You could summarize the differences like this:

    PHP as CGI with suPHP: You are very securely walled off from the other accounts on your shared server. If another
    account gets hacked, it probably cannot affect your site at all. However, if your account gets hacked, the hacker has
    complete freedom to wreak total havoc inside your site because they can use PHP to access/change anything they want. Since PHP
    runs as you, you have no ability to protect your files from a rogue PHP script.

    PHP as Apache module: You are not walled off from other accounts on your shared server. If another account gets hacked,
    PHP can be used to read your files, and any file or folder that you can write to using PHP, the other account can, too.
    However, if your account gets hacked, the vast majority of your files remain protected from malicious modification by
    PHP, because PHP when running inside your account doesn't have any greater privileges than it already has all of the time. It
    is only nobody, and most of your files are owned by your userID, so it can't change them or add files to your site. It can
    only write to your 666 files and can only put new files into your 777 folders.


    There is a common type of attack in which a malicious PHP script runs through a website opening every file with index in its
    name (index.htm, index.html, index.php...) and stuffs malicious code (iframes or scripts) into each of them. This type of
    attack is normally not possible with PHP as Apache module because the files are protected by their permissions settings
    (unless the permissions settings were wrong). If an Apache module configured website suffers this type of attack, it must have
    happened through FTP password theft, with the attacker downloading the files, modifying them, and re-uploading them. While
    using FTP, the attacker is acting as your userID and therefore has the ability to change the files. They couldn't have done
    it, in this case, with PHP.

Questions and comments are welcome in the discussion