If you don't make any mistakes, your PHP sources cannot be read from the outside: as long as apache is configured to handle .php files through mod_php, they will always be executed, never served raw.
However, mistakes are easy to make, and are frequently found in production code. Typical mistakes include:
- Path traversal vulnerabilities. The typical pattern is that you construct a filename based on some user input (e.g. a
$_GET
parameter), and then serve this file through, say, readfile
. For example, if you have readfile("/home/me/pages/{$_GET['pageid']}.html")
, an attacker can easily plant something like "../../../../../../../../../../../etc/shadow"
.
- PHP files with nonstandard extensions. Apache uses the extension to determine a file's MIME type, and then decides how to handle it based on that.
config.php
will be interpreted, but config.php.inc
will not; since .inc
is not a known extensions in most setups, Apache defaults to plain text, which means the source code can be requested over the net.
- Code upload. Typically, such a vulnerability arises when you have file uploads that are handled improperly, e.g. allowing arbitrary directories in the uploaded filename, or uploading to a location under the document root. When an attacker can plant
.php
files in a location where they get executed, it is possible to run arbitrary PHP code on your server, including code that reads other scripts and extracts passwords.
- Remote code execution vulnerabilities. Similar to code upload; if you have any
eval
, include
, system
, exec
or similar calls in your code, and their arguments are partially user-supplied, you may be in trouble - improperly sanitized inputs to any of these constructs can allow attackers to run arbitrary PHP code or shell commands.
- Displaying errors in the page output. Many errors and exception contain sensitive data, at least portions of the source code, but sometimes (e.g. PDOExceptions) even usernames and passwords.
- Apache configuration mistakes. Apache is a powerful thing, full of obscure features, and some of them have security implications.
In addition to avoiding these pitfalls, you should put only those files under the document root that are intended to be called directly; any includes, data files, configuration files, libraries, etc., go into directories outside the document root.