PHP is a study in bad security. The main idea pervading PHP is "ease
of use," and the mantra "don't make the developer go to any extra work
to get stuff done" applies in all cases. This is accomplished in PHP by
removing formalism from the language, allowing declaration of variables
on first use, initializing everything with preset values, and taking
every meaningful variable from a transaction and making it available. In
cases of collision with something more technical, the simple almost
always dominates in PHP.
One consequence of all this is that PHP allows users of a Web
application to override environment variables with user-supplied,
untrusted query variables. Thus, critical values such as the CWD and the
search path can be overwritten and directly controlled by a remote
anonymous user.
Another similar consequence is that variables can be directly
controlled and assigned from the user-controlled values supplied in GET
and POST request fields. So seemingly normal code like this, does
bizarre things:
while($count < 10){
// Do something
$count++;
}
Normally, this loop will execute its body ten times. The first
iteration will be an undefined zero, and further trips though the loop
will result in an increment of the variable $count. The problem is that
the coder does not initialize the variable to zero before entering the
loop. This is fine because PHP initializes the variable on declaration.
The result is code that seems to function, regardless of badness. The
problem is that a user of the Web application can supply a request such
as
and cause $count to start out at the value 9, resulting in only one
trip through the loop. Yerg.
Depending on the configuration, PHP may accept user-supplied variables
in place of environment variables. PHP initializes global variables for
all process environment variables, such as $PATH and $HOSTNAME. These
variables are of critical importance because they may be used in file or
network operations. If an attacker can supply a new $PATH variable (such
as PATH='/var'), the program may be exploitable.
PHP may also take field tags supplied in GET/POST requests and
transform them into global variables. This is the case with the $count
variable we explored in our previous example.
Consider another example of this problem in which a program defines a
variable called $tempfile. An attacker can supply a new temp file such
as $tempfile = "/etc/passwd". Then the temp file may get erased later
via a call to unlink($tempfile);. Now the passwd file has been erased—a
bad thing indeed on most OSs.
Also consider that the use of include() and require() first search
$PATH, and that using calls to the shell may execute crucial programs
such as ls. In this way, ls may be "Trojaned" (the attacker can modify
$PATH to cause a Trojan copy of ls to be loaded). This type of attack
could also apply to loadable libraries if $LD_LIBRARY_PATH is
modified.
Finally, some versions of PHP may pass user data to syslog as a format
string, thus exposing the application to a format string buffer
overflow.