<document>
  <header>
    <product>resin</product>
    <title>Quercus Security</title>
    
    <description>
      <p>Description of Quercus and PHP Security Issues</p>

    </description>
  </header>

  <body>
    <summary/>
    <localtoc/>

<s1 title="C language vulnerabilities">

<p>Since Quercus implements PHP in the Java language as opposed to C,
it is automatically protected from a number of C-language security
issues.  The most important issue is buffer and pointer overruns, but
also includes memory issues.
</p>

<s2 title="Buffer Overruns in C">

<p>In the C language, strings, arrays, and objects are all referenced by
pointers.  The simplest example of a security issue is the buffer
overflow.  The following example has a string of length 10, but the
code changes a value at location 20.  In Java, the equivalent code
would raise an exception.  In C, this code writes data at the location
20, even though it is beyond the end of the code and is almost
certainly pointing to other important information.</p>

<example title="example buffer overrun">
void
foo()
{
  char data[10];

  data[20] = '!';
}
</example>

<p>At best, this kind of error will cause a segmentation-violation and
force the program to exit, at worst it can create mini-programs which
an attacker can use to gain control of the web server.</p>

<p>The issue in a C program like PHP is that every single pointer
reference must be correct and checked for overruns by the application
code.  If the programmers miss a single instance, a hacker could use
that bug to run malicious code on the web server.</p>

<p>The issue does not apply just to arrays, but to all objects, strings, and
pointers, since all objects can be cast to a string and that pointer
can be used to modify any memory.</p>

<p>In a Java program like Quercus, this isn't an issue because Java
itself protects every array or object reference.  Java will catch any
application pointer bug or buffer overflow and throw an exception.
Java code can't create and execute mini-programs like C-code can.</p>

</s2>

<s2 title="PHP language engine">

<p>The first potential source of C-related bugs in PHP is in the
language implementation itself.  A language implementation consists of
a parser, an interpreter/compiler, and runtime objects like strings,
arrays, database connections, etc.</p>

<p>Quercus can run PHP in either interpreted or compiled modes. In the
interpreted mode, Quercus executes the parsed program directly.  In
the compiled mode, Quercus compiles the PHP code to Java code and then
executes Java code.  In both cases, the underlying execution uses the
Java virtual machine and Java's just-in-time compiler for
performance.  Quercus's execution engine is protected by Java's
implementation and the JDK is very solid and safe technology.</p>

<p>In contrast, PHP implements its own bytecode interpreter in C.
This means a bug in the PHP bytecode interpreter could result in a
pointer security problem, where that issue is absent from
Quercus's implementation.</p>

</s2>

<s2 title="PHP runtime objects">

<p>The basic runtime objects for PHP need to be implemented as well,
the strings, arrays, objects, etc.  Quercus implements these objects
as Java objects directly. PHP implements these objects as C objects.
The same issues that arise for the interpreter arise for the objects.
A pointer failure or failure to initialize data in a PHP array could
cause security problems in the C implementation, while an identical
bug in Quercus would merely throw an exception.</p>

</s2>

<s2 title="Memory Management">

<p>Quercus automatically uses Java's memory management and garbage
collection system.  This means any unused object can simply be dropped
and the garbage collector will automatically reuse the object at next
GC time.  The garbage collector simplifies the Quercus module code
(less code is less potential bugs) and makes certain kinds of memory
leaks impossible.</p>

<p>The C implementation of PHP needs to implement its own memory
management, using a reference counting system.  This means any library
code needs to explicitly dereference an object when it's done using
it.  Forgetting to do so creates a new bug.</p>

</s2>

<s2 title="Library/Module implementation">

<p>
Quercus libraries and modules are written in Java. PHP libraries
are written in C.  This implementation language choice means any
extension library for PHP is subject to the same security issues as
described above.  Not only does every aspect of the PHP language and
objects need to be correct, but all the libraries and modules need to
be correct.</p>

<p>In contrast, Quercus libraries are just Java programs.  Any
Quercus extension is automatically protected by the Java language.
So a site can confidently download a Quercus module from a site like
sourceforge and be confident that it doesn't introduce an additional
C-language security bug.</p>

</s2>

</s1>

<s1 title="PHP include visibility">

<p>Any significant PHP program will use <code>include</code> to
structure the code, executing code from another PHP file.  The
included files are valid PHP programs, but are not meant to be
browsed.  However, since the included files are valid PHP programs
they will be browsed and executed if a browser points to the
program.</p>

<p>Most PHP programs protect themselves by adding some extra code to
the top of every included file to check if they're being used
properly:</p>

<example title="inc.php example protection">
&lt;php?

if (! $check_include)
  die("illegal include file");

...
?>
</example>

<p>The include-protection code works, but does require the PHP
programmer to be careful about each included files.  Any mistake can
cause an unexpected file to be executed.</p>

<p>Quercus programmers can instead put all their included files in the WEB-INF
directory, e.g. in WEB-INF/php.  Any Java application server
will automatically protects all files in WEB-INF directory from all
browsing.  So the PHP include of WEB-INF/php/inc.php will execute
the included files, but that file is not browable by an external
user.</p>

<s2 title="Configuration file visibility">

<p>Often, PHP configuration will be written in PHP itself.
This scripting configuration makes customizing PHP programs very
simple and accessible without needing to learn a new syntax, but
runs into the same potential PHP include vulnerability listed above.
In Quercus, configuration files belong in the WEB-INF directory where
they are protected from malicious spying.
</p>

</s2>

<s2 title="Temporary and data file visibility">

<p>
Many applications need to create temporary file or store plain data
files.  Java applications are accustomed to using either WEB-INF as
their default data directory or configure an external temporary
location.  Because WEB-INF is protected, any temporary file is
protected as well.
</p>

</s2>

</s1>

<s1 title="PHP language issues">

<s2 title="register_globals">

<p>
Quercus does not implement the deprecated register_globals capability
of PHP.  So it is impossible for a misconfiguration to open that
particular vulnerability.
</p>

<p>
register_globals is a deprecated feature (disabled by default in PHP),
which automatically registered a form's data as PHP variables.  So the
register_globals feature opened a large security hole where an
attacker could post a bogus form with non-sensical variables to
confuse or reconfigure the script.
</p>

</s2>


</s1>

<s1 title="Cross site scripting (XSS)">

<p>Since cross-side scripting attacks prey on application errors, not the
language engine, both Quercus and PHP programs must take care to
filter their input.  See <a href="http://en.wikipedia.org/wiki/Cross_site_scripting">http://en.wikipedia.org/wiki/Cross_site_scripting</a>.</p>

<p>
The basic cross-site scripting vulnerability occurs when an
application trusts form data and redisplays it to a user.  For
example, a buggy bulletin board system might display a comment without
escaping the HTML.  Since HTML can include JavaScript, this could
allow a malicious commenter to leave some HTML which executed
JavaScript on a browser, e.g.
</p>

<example>
&lt;script language="javascript">alert("This is a bogus alert");&lt;/script>
</example>

<p>
The PHP libraries provide a number of functions to help protect
against cross-site scripting attacks.  A simple example might be:
</p>

<example>
&lt;?php

$clean['message'] = htmlentities($_GET['message']);

?>
</example>

<ul>
<li>htmlentities()</li>
<li>htmlspecialchars()</li>
<li>strtr()</li>
<li>strip_tags()</li>
<li>utf8_decode()</li>
</ul>

</s1>

<s1 title="URLs and Forms">

<p>URL and form POST data can be easily spoofed; it does not take a
sophisticated hacker to generate any HTTP input.  So any script that
takes data from the internet must validate the GET, header and POST data
before acting on it.</p>

<p>The dangers of this issue is apparent to anyone who looks at
web server logs and finds many examples of bogus URLs for programs
not even installed on the server.</p>

<s2 title="URLs and files">

<p>Because PHP can create strings so easily, it's temping to build
an application which selects a file based on the URL data, e.g. for
a URL <code>http://foo.com/index.php?page=submit.php</code>.</p>

<example title="Bogus index.php">
&lt;?php

include ("page/{$_GET['page']}");

?>
</example>

<p>Because that example does no validation, any PHP script on the
server at all could be displayed.  A better solution would be:</p>

<example title="Better index.php">
&lt;?php

$commands = array("comment" => "comment.php",
                  "display" => "display.php");

$clean_page = $commands[$_GET['page']];

if (! $clean_page)
  die();

</example>

</s2>

<s2 title="eval(), system(), and passthru()">

<p>Any command which interprets string as PHP or executes a system
command is especially dangerous.  Consider:</p>

<example title="bogus.php">
&lt;?php

eval($_GET['data']);
</example>

<p>If the URL was
<code>http://foo.com/bogus.php?data=passthru("cat
/etc/passwd")</code>, you'd
have exposed the server's passwords.</p>

<ul>
<li>addslashes()</li>
<li>escapeshellarg()</li>
<li>escapeshellcmd()</li>
<li>realpath()</li>
</ul>

</s2>

<s2 title="Database Injection Protection">

<p>In general, web data cannot be trusted.  This is especially true
for data that modifies the database.  The standard bad example is:</p>

<example title="php database injection">
&lt;?php

$sql = "INSERT INTO test VALUES ('{$_POST['data']}')";

?>
</example>

<p>With the previous bogus code, an attacker could add two records
with the following data:</p>

<example>
first'), ('second
</example>

<p>To protect against this, you can use the newer PDO interface to
avoid the issue entirely, or use escaping functions
like <code>mysql_escape_string()</code>.  The PDO interface has
two advantages: it works for all databases, and it's less likely to
forget to escape the data.   The PDO code might looks like:</p>

<example title='PDO bindValue INSERT code'>
&lt;?php

$pdo = new PDO("java:comp/env/jdbc/test");

$sql = "INSERT INTO test VALUES(?)";

$stmt = $pdo->prepare($sql);
$stmt->bindValue(1, $_POST['data']);
$stmt->execute();

</example>

<p>The older mysql-style escaping also exists, but newer code should
migrate to PDO:</p>


<example title='PDO bindValue INSERT code'>
&lt;?php

$clean_data = mysql_escape_string($_POST['data']);

$sql = "INSERT INTO test VALUES($clean_data)";

mysql_query($sql);
</example>

</s2>

</s1>

<s1 title="Database Security issues">

<s2 title="Configuration files and passwords">

<p>PHP programs often configure the databases inside the PHP code
itself or in included files.  As mentioned above, Quercus can make
the confguration more secure from prying eyes by putting the
configuration into the WEB-INF directory.</p>

<p>In addition, Quercus can use Java DataSources directly, taking the
configuration out of the PHP code entirely.  This configuration will
take precedence over the PHP code, so you can secure an existing
application without any changes.  The Quercus configuration looks
like:
</p>

<example title="WEB-INF/resin-web.xml configuration of Java database">
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;database jndi-name="jdbc/test">
    &lt;driver type="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource"
     &lt;url>jdbc:mysql://localhost:3306/test&lt;/url>
     &lt;user>foo&lt;/user>
     &lt;password>bar&lt;/password>
   &lt;/driver>
  &lt;/database>

  &lt;servlet-mapping url-pattern="*.php"
                   servlet-class="com.caucho.quercus.servlet.QuercusServlet">
    &lt;init>
      &lt;database>jdbc/test&lt;/database>
    &lt;/init>
  &lt;/servlet-mapping>
&lt;/web-app>
</example>

</s2>

</s1>

<s1 title="Session Security">

<s2 title="URL-based sessions">

<p>We strongly discourage the use of URL-based sessions as a serious
security risk.  By default, Quercus disables URL-based sessions.
URL-based sessions are particular problems because users will blindly
cut and paste URLs with their session information and post them in
public places.  Because these kinds of security breaches occur by
simple mistakes and not concerted hacker attempts, they are far more
common and serious.</p>

<p>The URL-based sessions in PHP look something like:</p>

<example>
http://foo.com/test.php?PHPSESSID=asdf
</example>

</s2>

<s2 title="Cookie Hijacking">

<p>
Normal HTTP requests are sent in cleartext across the internet,
including the cookie values which keep track of sessions.  Because the
data is in the clear, it's possible for a malicious hacker to look at
the HTTP request, copy the cookie, and forward a new request to a web
site.  For this reason, you should use SSL for any session that passes
any sort of important data, and also timeout any sessions which carry
important information.
</p>

</s2>

</s1>

<s1 title="Extra information">

<p>By default, PHP sends error messages to the browser.  On a
production system, this should be turned off:</p>

<example>
&lt;web-app xmlns="http://caucho.com/ns/resin">

  &lt;servlet-mapping url-pattern="*.php"
                    servlet-class="com.caucho.quercus.QuercusServlet">
    &lt;init>
      &lt;php-ini display_errors="Off" log_errors="On"/>
    &lt;/init>
  &lt;/servlet-mapping>

&lt;/web-app>
</example>

</s1>

  </body>
</document>