On Thursday 15 January 2004 13:12, Gabor Hojtsy wrote:
> > > > splitting huge files makes life for translation teams easier.
> > > > Therefore I am always +1 for splitting.
> > > >
> > > > The functions source xml-files are read for review :
> > > > http://www.holliwell.de/security/security.tar.bz2
> > > > along with the compiled security chapter:
> > > > http://www.holliwell.de/security/
> > >
> > > As it seems there are some small changes made with this split (a title
> > > was added for the intro sectin). Since the split would be good to be
> > > done for all languages, this is not a good idea, as the change is hard
> > > to track with the split. Changes should be made IMHO after the split.
> >
> > I consider this rather a real split of the security chapter, than just a
> > "normal" change in the en version. Trans teams can pick them up as they
> > find the time.
> > Btw, as long as the old index.xml is splitted up, the new one with
> > changed content would replace the original one. So there is no version we
> > could refer to claimed by "Last change was don in Rev..."
>
> Well, technically the split just removes a lot of lines from
> security/index.xml and adds a few, so the old change history will be kept
> on the file. It might be enough to just add a comment to index.xml that
> what was the last version before the split, so translation people can pick
> up the changes between their revision and that revision before splitting.
> That also provides a good reason not to split the file in the
> translations, since the monolitic index.xml will still work, and it seems
> to be easier to let translations teams split the files themselfs after
> they picked up the changes done before the split.
>
> It is still important BTW that there should be no content change in the
> split. If a content change is needed (eg. new section title, etc), then
> that should be done in a separate commit on the splitted files. BTW the
> sections need to be elevated one level, so the section/section oddity in
> the TOC can be solved. But these should be done after the split IMHO.
>

No content changes, just split by sect1 and proper linking and adding the new 
files along with the above mentioned comments, diff attached
Any objections to commit?

Friedhelm




-- 
http://www.jungle-world.com/
Index: index.xml
===================================================================
RCS file: /repository/phpdoc/en/security/index.xml,v
retrieving revision 1.66
diff -u -r1.66 index.xml
--- index.xml   6 Jan 2004 09:22:21 -0000       1.66
+++ index.xml   25 Jan 2004 23:48:03 -0000
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="iso-8859-1"?>
 <!-- $Revision: 1.66 $ -->
+<!-- Last Revision before split: 1.66 -->
  <chapter id="security.index">
   <title>Security</title>
 
@@ -38,1270 +39,16 @@
    coding for different levels of security.
   </simpara>
 
-  <sect1 id="security.general">
-   <title>General considerations</title>
-   <simpara>
-    A completely secure system is a virtual impossibility, so an
-    approach often used in the security profession is one of balancing
-    risk and usability. If every variable submitted by a user required
-    two forms of biometric validation (such as a retinal scan and a
-    fingerprint), you would have an extremely high level of
-    accountability. It would also take half an hour to fill out a fairly
-    complex form, which would tend to encourage users to find ways of
-    bypassing the security.
-   </simpara>
-   <simpara>
-    The best security is often inobtrusive enough to suit the
-    requirements without the user being prevented from accomplishing
-    their work, or over-burdening the code author with excessive
-    complexity. Indeed, some security attacks are merely exploits of
-    this kind of overly built security, which tends to erode over time.
-   </simpara>
-   <simpara>
-    A phrase worth remembering: A system is only as good as the weakest
-    link in a chain. If all transactions are heavily logged based on
-    time, location, transaction type, etc. but the user is only
-    verified based on a single cookie, the validity of tying the users
-    to the transaction log is severely weakened.
-   </simpara>
-   <simpara>
-    When testing, keep in mind that you will not be able to test all
-    possibilities for even the simplest of pages. The input you
-    may expect will be completely unrelated to the input given by
-    a disgruntled employee, a cracker with months of time on their
-    hands, or a housecat walking across the keyboard. This is why it's
-    best to look at the code from a logical perspective, to discern
-    where unexpected data can be introduced, and then follow how it is
-    modified, reduced, or amplified.
-   </simpara>
-   <simpara>
-    The Internet is filled with people trying to make a name for
-    themselves by breaking your code, crashing your site, posting
-    inappropriate content, and otherwise making your day interesting.
-    It doesn't matter if you have a small or large site, you are
-    a target by simply being online, by having a server that can be
-    connected to. Many cracking programs do not discern by size, they
-    simply trawl massive IP blocks looking for victims. Try not to
-    become one.
-   </simpara>
-  </sect1>
-
-  <sect1 id="security.cgi-bin">
-   <title>Installed as CGI binary</title>
-
-   <sect2 id="security.cgi-bin.attacks">
-    <title>Possible attacks</title>
-    <simpara>
-     Using PHP as a <acronym>CGI</acronym> binary is an option for
-     setups that for some reason do not wish to integrate PHP as a
-     module into server software (like Apache), or will use PHP with
-     different kinds of CGI wrappers to create safe chroot and setuid
-     environments for scripts.  This setup usually involves installing
-     executable PHP binary to the web server cgi-bin directory.  CERT
-     advisory <ulink url="&url.cert;">CA-96.11</ulink> recommends
-     against placing any interpreters into cgi-bin.  Even if the PHP
-     binary can be used as a standalone interpreter, PHP is designed
-     to prevent the attacks this setup makes possible:
-    </simpara>
-    <itemizedlist>
-     <listitem>
-      <simpara>
-       Accessing system files: <filename
-       role="url">http://my.host/cgi-bin/php?/etc/passwd</filename>
-      </simpara>
-      <simpara>
-       The query information in a url after the question mark (?)  is
-       passed as command line arguments to the interpreter by the CGI
-       interface.  Usually interpreters open and execute the file
-       specified as the first argument on the command line.
-      </simpara>
-      <simpara>
-       When invoked as a CGI binary, PHP refuses to interpret the
-       command line arguments.
-      </simpara>
-     </listitem>
-     <listitem>
-      <simpara>
-       Accessing any web document on server: <filename
-       role="url">http://my.host/cgi-bin/php/secret/doc.html</filename>
-      </simpara>
-      <simpara>
-       The path information part of the url after the PHP binary name,
-       <filename role="uri">/secret/doc.html</filename> is
-       conventionally used to specify the name of the file to be
-       opened and interpreted by the <acronym>CGI</acronym> program.
-       Usually some web server configuration directives (Apache:
-       Action) are used to redirect requests to documents like
-       <filename
-       role="url">http://my.host/secret/script.php</filename> to the
-       PHP interpreter.  With this setup, the web server first checks
-       the access permissions to the directory <filename
-       role="uri">/secret</filename>, and after that creates the
-       redirected request <filename
-       role="url">http://my.host/cgi-bin/php/secret/script.php</filename>.
-       Unfortunately, if the request is originally given in this form,
-       no access checks are made by web server for file <filename
-       role="uri">/secret/script.php</filename>, but only for the
-       <filename role="uri">/cgi-bin/php</filename> file.  This way
-       any user able to access <filename
-       role="uri">/cgi-bin/php</filename> is able to access any
-       protected document on the web server.
-      </simpara>
-      <simpara>
-       In PHP, compile-time configuration option <link
-       
linkend="install.configure.enable-force-cgi-redirect">--enable-force-cgi-redirect</link>
-       and runtime configuration directives <link
-       linkend="ini.doc-root">doc_root</link> and <link
-       linkend="ini.user-dir">user_dir</link> can be used to prevent
-       this attack, if the server document tree has any directories
-       with access restrictions.  See below for full the explanation
-       of the different combinations.
-      </simpara>
-     </listitem>
-    </itemizedlist>
-   </sect2>
-
-   <sect2 id="security.cgi-bin.default">
-    <title>Case 1: only public files served</title>
-
-    <simpara>
-     If your server does not have any content that is not restricted
-     by password or ip based access control, there is no need for
-     these configuration options.  If your web server does not allow
-     you to do redirects, or the server does not have a way to
-     communicate to the PHP binary that the request is a safely
-     redirected request, you can specify the option <link
-     
linkend="install.configure.enable-force-cgi-redirect">--enable-force-cgi-redirect</link>
-     to the configure script.  You still have to make sure your PHP
-     scripts do not rely on one or another way of calling the script,
-     neither by directly <filename
-     role="php">http://my.host/cgi-bin/php/dir/script.php</filename>
-     nor by redirection <filename
-     role="php">http://my.host/dir/script.php</filename>.
-    </simpara>
-    <simpara>
-     Redirection can be configured in Apache by using AddHandler and
-     Action directives (see below).
-    </simpara>
-   </sect2>
-
-   <sect2 id="security.cgi-bin.force-redirect">
-    <title>Case 2: using --enable-force-cgi-redirect</title>
-    <simpara>
-     This compile-time option prevents anyone from calling PHP
-     directly with a url like <filename
-     role="php">http://my.host/cgi-bin/php/secretdir/script.php</filename>.
-     Instead, PHP will only parse in this mode if it has gone through
-     a web server redirect rule.
-    </simpara>
-    <simpara>
-     Usually the redirection in the Apache configuration is done with
-     the following directives:
-    </simpara>
-    <programlisting role="apache-conf">
-<![CDATA[
-Action php-script /cgi-bin/php
-AddHandler php-script .php
-]]>
-    </programlisting>
-    <simpara>
-     This option has only been tested with the Apache web server, and
-     relies on Apache to set the non-standard CGI environment variable
-     <envar>REDIRECT_STATUS</envar> on redirected requests.  If your
-     web server does not support any way of telling if the request is
-     direct or redirected, you cannot use this option and you must use
-     one of the other ways of running the CGI version documented
-     here.
-    </simpara>
-   </sect2>
-
-   <sect2 id="security.cgi-bin.doc-root">
-    <title>Case 3: setting doc_root or user_dir</title>
-    <simpara>
-     To include active content, like scripts and executables, in the
-     web server document directories is sometimes considered an insecure
-     practice.  If, because of some configuration mistake, the scripts
-     are not executed but displayed as regular HTML documents, this
-     may result in leakage of intellectual property or security
-     information like passwords.  Therefore many sysadmins will prefer
-     setting up another directory structure for scripts that are
-     accessible only through the PHP CGI, and therefore always
-     interpreted and not displayed as such.
-    </simpara>
-    <simpara>
-     Also if the method for making sure the requests are not
-     redirected, as described in the previous section, is not
-     available, it is necessary to set up a script doc_root that is
-     different from web document root.
-    </simpara>
-    <simpara>
-     You can set the PHP script document root by the configuration
-     directive <link linkend="ini.doc-root">doc_root</link> in the
-     <link linkend="configuration.file">configuration file</link>, or
-     you can set the environment variable
-     <envar>PHP_DOCUMENT_ROOT</envar>.  If it is set, the CGI version
-     of PHP will always construct the file name to open with this
-     <parameter>doc_root</parameter> and the path information in the
-     request, so you can be sure no script is executed outside this
-     directory (except for <parameter>user_dir</parameter>
-     below).
-    </simpara>
-    <simpara>
-     Another option usable here is <link
-     linkend="ini.user-dir">user_dir</link>.  When user_dir is unset,
-     only thing controlling the opened file name is
-     <parameter>doc_root</parameter>.  Opening an url like <filename
-     role="url">http://my.host/~user/doc.php</filename> does not
-     result in opening a file under users home directory, but a file
-     called <filename role="uri">~user/doc.php</filename> under
-     doc_root (yes, a directory name starting with a tilde
-     [<literal>~</literal>]).
-    </simpara>
-    <simpara>
-     If user_dir is set to for example <filename
-     role="dir">public_php</filename>, a request like <filename
-     role="url">http://my.host/~user/doc.php</filename> will open a
-     file called <filename>doc.php</filename> under the directory
-     named <filename role="dir">public_php</filename> under the home
-     directory of the user.  If the home of the user is <filename
-     role="dir">/home/user</filename>, the file executed is
-     <filename>/home/user/public_php/doc.php</filename>.
-    </simpara>
-    <simpara>
-     <parameter>user_dir</parameter> expansion happens regardless of
-     the <parameter>doc_root</parameter> setting, so you can control
-     the document root and user directory access
-     separately.
-    </simpara>
-   </sect2>
-
-   <sect2 id="security.cgi-bin.shell">
-    <title>Case 4: PHP parser outside of web tree</title>
-    <para>
-     A very secure option is to put the PHP parser binary somewhere
-     outside of the web tree of files.  In <filename
-     role="dir">/usr/local/bin</filename>, for example.  The only real
-     downside to this option is that you will now have to put a line
-     similar to:
-     <informalexample>
-      <programlisting>
-<![CDATA[
-#!/usr/local/bin/php
-]]>
-      </programlisting>
-     </informalexample>
-     as the first line of any file containing PHP tags.  You will also
-     need to make the file executable.  That is, treat it exactly as
-     you would treat any other CGI script written in Perl or sh or any
-     other common scripting language which uses the
-     <literal>#!</literal> shell-escape mechanism for launching
-     itself.
-    </para>
-    <para>
-     To get PHP to handle <envar>PATH_INFO</envar> and
-     <envar>PATH_TRANSLATED</envar> information correctly with this
-     setup, the PHP parser should be compiled with the <link
-     linkend="install.configure.enable-discard-path">--enable-discard-path</link>
-     configure option.
-    </para>
-   </sect2>
-
-  </sect1>
-
-  <sect1 id="security.apache">
-   <title>Installed as an Apache module</title>
-   <simpara>
-    When PHP is used as an Apache module it inherits Apache's user
-    permissions (typically those of the "nobody" user). This has several
-    impacts on security and authorization. For example, if you are using
-    PHP to access a database, unless that database has built-in access
-    control, you will have to make the database accessible to the
-    "nobody" user. This means a malicious script could access and modify
-    the database, even without a username and password. It's entirely
-    possible that a web spider could stumble across a database
-    administrator's web page, and drop all of your databases. You can
-    protect against this with Apache authorization, or you can design
-    your own access model using LDAP, &htaccess; files, etc. and include
-    that code as part of your PHP scripts.
-   </simpara>
-   <simpara>
-    Often, once security is established to the point where the PHP user
-    (in this case, the apache user) has very little risk attached to it,
-    it is discovered that PHP is now prevented from writing any files
-    to user directories. Or perhaps it has been prevented from accessing
-    or changing databases. It has equally been secured from writing
-    good and bad files, or entering good and bad database transactions.
-   </simpara>
-   <simpara>
-    A frequent security mistake made at this point is to allow apache
-    root permissions, or to escalate apache's abilitites in some other
-    way.
-   </simpara>
-   <simpara>
-    Escalating the Apache user's permissions to root is extremely
-    dangerous and may compromise the entire system, so sudo'ing,
-    chroot'ing, or otherwise running as root should not be considered by
-    those who are not security professionals.
-   </simpara>
-   <simpara>
-    There are some simpler solutions. By using
-    <link linkend="ini.open-basedir">open_basedir</link> you can control and restrict 
what
-    directories are allowed to be used for PHP. You can also set up
-    apache-only areas, to restrict all web based activity to non-user,
-    or non-system, files.
-   </simpara>
-  </sect1>
-
-  <sect1 id="security.filesystem">
-   <title>Filesystem Security</title>
-   <simpara>
-    PHP is subject to the security built into most server systems with
-    respect to permissions on a file and directory basis. This allows
-    you to control which files in the filesystem may be read. Care
-    should be taken with any files which are world readable to ensure
-    that they are safe for reading by all users who have access to that
-    filesystem.
-   </simpara>
-   <simpara>
-    Since PHP was designed to allow user level access to the filesystem,
-    it's entirely possible to write a PHP script that will allow you
-    to read system files such as /etc/passwd, modify your ethernet
-    connections, send massive printer jobs out, etc. This has some
-    obvious implications, in that you need to ensure that the files
-    that you read from and write to are the appropriate ones.
-   </simpara>
-   <simpara>
-    Consider the following script, where a user indicates that they'd
-    like to delete a file in their home directory. This assumes a
-    situation where a PHP web interface is regularly used for file
-    management, so the Apache user is allowed to delete files in
-    the user home directories.
-   </simpara>
-   <para>
-    <example>
-     <title>Poor variable checking leads to....</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-// remove a file from the user's home directory
-$username = $_POST['user_submitted_name'];
-$homedir = "/home/$username";
-$file_to_delete = "$userfile";
-unlink ("$homedir/$userfile");
-echo "$file_to_delete has been deleted!";
-?>
-]]>
-     </programlisting>
-    </example>
-   Since the username is postable from a user form, they can submit
-   a username and file belonging to someone else, and delete files.
-   In this case, you'd want to use some other form of authentication.
-   Consider what could happen if the variables submitted were
-   "../etc/" and "passwd". The code would then effectively read:
-    <example>
-     <title>... A filesystem attack</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-// removes a file from anywhere on the hard drive that
-// the PHP user has access to. If PHP has root access:
-$username = "../etc/";
-$homedir = "/home/../etc/";
-$file_to_delete = "passwd";
-unlink ("/home/../etc/passwd");
-echo "/home/../etc/passwd has been deleted!";
-?>
-]]>
-     </programlisting>
-    </example>
-    There are two important measures you should take to prevent these
-    issues.
-    <itemizedlist>
-     <listitem>
-      <simpara>
-       Only allow limited permissions to the PHP web user binary.
-      </simpara>
-     </listitem>
-     <listitem>
-      <simpara>
-       Check all variables which are submitted.
-      </simpara>
-     </listitem>
-    </itemizedlist>
-    Here is an improved script:
-    <example>
-     <title>More secure file name checking</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-// removes a file from the hard drive that
-// the PHP user has access to.
-$username = $_SERVER['REMOTE_USER']; // using an authentication mechanisim
-
-$homedir = "/home/$username";
-
-$file_to_delete = basename("$userfile"); // strip paths
-unlink ($homedir/$file_to_delete);
-
-$fp = fopen("/home/logging/filedelete.log","+a"); //log the deletion
-$logstring = "$username $homedir $file_to_delete";
-fputs ($fp, $logstring);
-fclose($fp);
-
-echo "$file_to_delete has been deleted!";
-?>
-]]>
-     </programlisting>
-    </example>
-    However, even this is not without it's flaws. If your authentication
-    system allowed users to create their own user logins, and a user
-    chose the login "../etc/", the system is once again exposed. For
-    this reason, you may prefer to write a more customized check:
-    <example>
-     <title>More secure file name checking</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-$username = $_SERVER['REMOTE_USER']; // using an authentication mechanisim
-$homedir = "/home/$username";
-
-if (!ereg('^[^./][^/]*$', $userfile))
-     die('bad filename'); //die, do not process
-
-if (!ereg('^[^./][^/]*$', $username))
-     die('bad username'); //die, do not process
-//etc...
-?>
-]]>
-     </programlisting>
-    </example>
-   </para>
-   <para>
-    Depending on your operating system, there are a wide variety of files
-    which you should be concerned about, including device entries (/dev/
-    or COM1), configuration files (/etc/ files and the .ini files),
-    well known file storage areas (/home/, My Documents), etc. For this
-    reason, it's usually easier to create a policy where you forbid
-    everything except for what you explicitly allow.
-   </para>
-  </sect1>
-
-  <sect1 id="security.database">
-   <title>Database Security</title>
-
-   <simpara>
-    Nowadays, databases are cardinal components of any web based application by
-    enabling websites to provide varying dynamic content. Since very sensitive
-    or secret information can be stored in a database, you should strongly
-    consider protecting your databases.
-   </simpara>
-   <simpara>
-    To retrieve or to store any information you need to connect to the database,
-    send a legitimate query, fetch the result, and close the connection.
-    Nowadays, the commonly used query language in this interaction is the
-    Structured Query Language (SQL). See how an attacker can <link
-    linkend="security.database.sql-injection">tamper with an SQL query</link>.
-   </simpara>
-   <simpara>
-    As you can surmise, PHP cannot protect your database by itself. The
-    following sections aim to be an introduction into the very basics of how to
-    access and manipulate databases within PHP scripts.
-   </simpara>
-   <simpara>
-    Keep in mind this simple rule: defense in depth. The more places you
-    take action to increase the protection of your database, the less
-    probability of an attacker succeeding in exposing or abusing any stored
-    information. Good design of the database schema and the application
-    deals with your greatest fears.
-   </simpara>
-
-   <sect2 id="security.database.design">
-    <title>Designing Databases</title>
-     <simpara>
-      The first step is always to create the database, unless you want to use
-      one from a third party. When a database is created, it is
-      assigned to an owner, who executed the creation statement. Usually, only
-      the owner (or a superuser) can do anything with the objects in that
-      database, and in order to allow other users to use it, privileges must be
-      granted.
-     </simpara>
-     <simpara>
-      Applications should never connect to the database as its owner or a
-      superuser, because these users can execute any query at will, for
-      example, modifying the schema (e.g. dropping tables) or deleting its
-      entire content.
-     </simpara>
-     <simpara>
-      You may create different database users for every aspect of your
-      application with very limited rights to database objects. The most
-      required privileges should be granted only, and avoid that the same user
-      can interact with the database in different use cases. This means that if
-      intruders gain access to your database using your applications credentials,
-      they can only effect as many changes as your application can.
-     </simpara>
-     <simpara>
-      You are encouraged not to implement all the business logic in the web
-      application (i.e. your script), instead do it in the database schema
-      using views, triggers or rules. If the system evolves, new ports will be
-      intended to open to the database, and you have to re-implement the logic
-      in each separate database client. Over and above, triggers can be used
-      to transparently and automatically handle fields, which often provides
-      insight when debugging problems with your application or tracing back
-      transactions.
-     </simpara>
-   </sect2>
-
-   <sect2 id="security.database.connection">
-    <title>Connecting to Database</title>
-    <simpara>
-     You may want to estabilish the connections over SSL to encrypt
-     client/server communications for increased security, or you can use ssh
-     to encrypt the network connection between clients and the database server.
-     If either of these is used, then monitoring your traffic and gaining
-     information about your database will be difficult for a would-be attacker.
-    </simpara>
-    <!--simpara>
-     If your database server has native SSL support, consider using <link
-     linkend="ref.openssl">OpenSSL functions</link> in communication between
-     PHP and database via SSL.
-    </simpara-->
-   </sect2>
-
-   <sect2 id="security.database.storage">
-    <title>Encrypted Storage Model</title>
-    <simpara>
-     SSL/SSH protects data travelling from the client to the server, SSL/SSH
-     does not protect the persistent data stored in a database. SSL is an
-     on-the-wire protocol.
-    </simpara>
-    <simpara>
-     Once an attacker gains access to your database directly (bypassing the
-     webserver), the stored sensitive data may be exposed or misused, unless
-     the information is protected by the database itself. Encrypting the data
-     is a good way to mitigate this threat, but very few databases offer this
-     type of data encryption.
-    </simpara>
-    <simpara>
-     The easiest way to work around this problem is to first create your own
-     encryption package, and then use it from within your PHP scripts. PHP
-     can assist you in this with several extensions, such as <link
-     linkend="ref.mcrypt">Mcrypt</link> and <link
-     linkend="ref.mhash">Mhash</link>, covering a wide variety of encryption
-     algorithms. The script encrypts the data before inserting it into the database, 
and decrypts
-     it when retrieving. See the references for further examples of how
-     encryption works.
-    </simpara>
-    <simpara>
-     In case of truly hidden data, if its raw representation is not needed
-     (i.e. not be displayed), hashing may also be taken into consideration.
-     The well-known example for the hashing is storing the MD5 hash of a
-     password in a database, instead of the password itself. See also
-     <function>crypt</function> and <function>md5</function>.
-    </simpara>
-    <example>
-     <title>Using hashed password field</title>
-     <programlisting role="php">
-<![CDATA[
-// storing password hash
-$query  = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
-            addslashes($username), md5($password));
-$result = pg_exec($connection, $query);
-
-// querying if user submitted the right password
-$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';",
-            addslashes($username), md5($password));
-$result = pg_exec($connection, $query);
-
-if (pg_numrows($result) > 0) {
-    echo "Welcome, $username!";
-}
-else {
-    echo "Authentication failed for $username.";
-}
-]]>
-     </programlisting>
-    </example>
-   </sect2>
-
-   <sect2 id="security.database.sql-injection">
-    <title>SQL Injection</title>
-    <simpara>
-     Many web developers are unaware of how SQL queries can be tampered with,
-     and assume that an SQL query is a trusted command. It means that SQL
-     queries are able to circumvent access controls, thereby bypassing standard
-     authentication and authorization checks, and sometimes SQL queries even
-     may allow access to host operating system level commands.
-    </simpara>
-    <simpara>
-     Direct SQL Command Injection is a technique where an attacker creates or
-     alters existing SQL commands to expose hidden data, or to override valuable
-     ones, or even to execute dangerous system level commands on the database
-     host. This is accomplished by the application taking user input and
-     combining it with static parameters to build a SQL query. The following
-     examples are based on true stories, unfortunately.
-    </simpara>
-    <para>
-     Owing to the lack of input validation and connecting to the database on
-     behalf of a superuser or the one who can create users, the attacker
-     may create a superuser in your database.
-     <example>
-      <title>
-       Splitting the result set into pages ... and making superusers
-       (PostgreSQL and MySQL)
-      </title>
-      <programlisting role="php">
-<![CDATA[
-$offset = argv[0]; // beware, no input validation!
-$query  = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
-// with PostgreSQL 
-$result = pg_exec($conn, $query);
-// with MySQL
-$result = mysql_query($query);
-]]>
-      </programlisting>
-     </example>
-      Normal users click on the 'next', 'prev' links where the 
<varname>$offset</varname>
-      is encoded into the URL. The script expects that the incoming
-      <varname>$offset</varname> is a decimal number. However, what if someone tries 
to
-      break in by appending a <function>urlencode</function>'d form of the
-      following to the URL 
-      <informalexample>
-       <programlisting>
-<![CDATA[
-// in case of PostgreSQL
-0;
-insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
-    select 'crack', usesysid, 't','t','crack'
-    from pg_shadow where usename='postgres';
---
-
-// in case of MySQL
-0;
-UPDATE user SET Password=PASSWORD('crack') WHERE user='root';
-FLUSH PRIVILEGES;
-]]>
-       </programlisting>
-      </informalexample>
-      If it happened, then the script would present a superuser access to him.
-      Note that <literal>0;</literal> is to supply a valid offset to the
-      original query and to terminate it.
-    </para>
-    <note>
-     <para>
-      It is common technique to force the SQL parser to ignore the rest of the
-      query written by the developer with <literal>--</literal> which is the
-      comment sign in SQL.
-     </para>
-    </note>
-    <para>
-     A feasible way to gain passwords is to circumvent your search result pages.
-     The only thing the attacker needs to do is to see if there are any submitted 
variables
-     used in SQL statements which are not handled properly. These filters can be set
-     commonly in a preceding form to customize <literal>WHERE, ORDER BY, 
-     LIMIT</literal> and <literal>OFFSET</literal> clauses in 
<literal>SELECT</literal>
-     statements. If your database supports the <literal>UNION</literal> construct, 
-     the attacker may try to append an entire query to the original one to list 
-     passwords from an arbitrary table. Using encrypted password fields is 
-     strongly encouraged.
-     <example>
-      <title>
-       Listing out articles ... and some passwords (any database server)
-      </title>
-      <programlisting role="php">
-<![CDATA[
-$query  = "SELECT id, name, inserted, size FROM products
-                  WHERE size = '$size'
-                  ORDER BY $order LIMIT $limit, $offset;";
-$result = odbc_exec($conn, $query);
-]]>
-      </programlisting>
-     </example>
-     The static part of the query can be combined with another
-     <literal>SELECT</literal> statement which reveals all passwords:
-     <informalexample>
-      <programlisting>
-<![CDATA[
-'
-union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from 
usertable;
---
-]]>
-      </programlisting>
-     </informalexample>
-     If this query (playing with the <literal>'</literal> and
-     <literal>--</literal>) were assigned to one of the variables used in
-     <varname>$query</varname>, the query beast awakened.
-    </para>
-    <para>
-     SQL UPDATE's are also susceptible to attack. These queries are
-     also threatened by chopping and appending an entirely new query to it. But
-     the attacker might fiddle with the <literal>SET</literal> clause. In this
-     case some schema information must be possessed to manipulate the query
-     successfully. This can be acquired by examining the form variable names, or
-     just simply brute forcing. There are not so many naming conventions for
-     fields storing passwords or usernames.
-     <example>
-     <title>
-      From resetting a password ... to gaining more privileges (any database server)
-     </title>
-      <programlisting role="php">
-<![CDATA[
-$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
-]]>
-      </programlisting>
-     </example>
-     But a malicious user sumbits the value
-     <literal>' or uid like'%admin%'; --</literal> to <varname>$uid</varname> to
-     change the admin's password, or simply sets <varname>$pwd</varname> to
-     <literal>"hehehe', admin='yes', trusted=100 "</literal> (with a trailing
-     space) to gain more privileges. Then, the query will be twisted:
-     <informalexample>
-      <programlisting role="php">
-<![CDATA[
-// $uid == ' or uid like'%admin%'; --
-$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";
-
-// $pwd == "hehehe', admin='yes', trusted=100 "
-$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE ...;"
-]]>
-      </programlisting>
-     </informalexample>
-    </para>
-    <para>
-     A frightening example how operating system level commands can be accessed
-     on some database hosts.
-     <example>
-     <title>Attacking the database hosts operating system (MSSQL Server)</title>
-      <programlisting role="php">
-<![CDATA[
-$query  = "SELECT * FROM products WHERE id LIKE '%$prod%'";
-$result = mssql_query($query);
-]]>
-      </programlisting>
-     </example>
-     If attacker submits the value
-     <literal>a%' exec master..xp_cmdshell 'net user test testpass /ADD' --</literal>
-     to <varname>$prod</varname>, then the <varname>$query</varname> will be:
-     <informalexample>
-      <programlisting role="php">
-<![CDATA[
-$query  = "SELECT * FROM products
-                    WHERE id LIKE '%a%'
-                    exec master..xp_cmdshell 'net user test testpass /ADD'--";
-$result = mssql_query($query);
-]]>
-      </programlisting>
-     </informalexample>
-     MSSQL Server executes the SQL statements in the batch including a command
-     to add a new user to the local accounts database. If this application
-     were running as <literal>sa</literal> and the MSSQLSERVER service is
-     running with sufficient privileges, the attacker would now have an
-     account with which to access this machine.
-    </para>
-    <note>
-     <para>
-      Some of the examples above is tied to a specific database server. This
-      does not mean that a similar attack is impossible against other products.
-      Your database server may be similarly vulnerable in another manner.
-     </para>
-    </note>
-
-    <sect3 id="security.database.avoiding">
-     <title>Avoiding techniques</title>
-     <simpara>
-      You may plead that the attacker must possess a piece of information
-      about the database schema in most examples. You are right, but you
-      never know when and how it can be taken out, and if it happens,
-      your database may be exposed. If you are using an open source, or
-      publicly available database handling package, which may belong to a
-      content management system or forum, the intruders easily produce
-      a copy of a piece of your code. It may be also a security risk if it
-      is a poorly designed one.
-     </simpara>
-     <simpara>
-      These attacks are mainly based on exploiting the code not being written
-      with security in mind. Never trust any kind of input, especially that
-      which comes from the client side, even though it comes from a select box,
-      a hidden input field or a cookie. The first example shows that such a
-      blameless query can cause disasters.
-     </simpara>
-
-     <itemizedlist>
-      <listitem>
-       <simpara>
-        Never connect to the database as a superuser or as the database owner.
-        Use always customized users with very limited privileges.
-       </simpara>
-      </listitem>
-      <listitem>
-       <simpara>
-        Check if the given input has the expected data type. PHP has
-        a wide range of input validating functions, from the simplest ones
-        found in <link linkend="ref.variables">Variable Functions</link> and
-        in <link linkend="ref.ctype">Character Type Functions</link>
-        (e.g. <function>is_numeric</function>, <function>ctype_digit</function>
-        respectively) and onwards to the
-        <link linkend="ref.pcre">Perl compatible Regular Expressions</link>
-        support.
-       </simpara>
-      </listitem>
-      <listitem>
-       <para>
-        If the application waits for numerical input, consider verifying data
-        with <function>is_numeric</function>, or silently change its type
-        using <function>settype</function>, or use its numeric representation
-        by <function>sprintf</function>.
-        <example>
-         <title>A more secure way to compose a query for paging</title>
-         <programlisting role="php">
-<![CDATA[
-settype($offset, 'integer');
-$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
-
-// please note %d in the format string, using %s would be meaningless
-$query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
-                 $offset);
-]]>
-         </programlisting>
-        </example>
-       </para>
-      </listitem>
-      <listitem>
-       <simpara>
-        Quote each non numeric user input which is passed to the database with
-        <function>addslashes</function> or <function>addcslashes</function>.
-        See <link linkend="security.database.storage">the first example</link>.
-        As the examples shows, quotes burnt into the static part of the query
-        is not enough, and can be easily cracked.
-       </simpara>
-      </listitem>
-      <listitem>
-       <simpara>
-        Do not print out any database specific information, especially
-        about the schema, by fair means or foul. See also <link
-        linkend="security.errors">Error Reporting</link> and <link
-        linkend="ref.errorfunc">Error Handling and Logging Functions</link>.
-       </simpara>
-      </listitem>
-      <listitem>
-       <simpara>
-        You may use stored procedures and previously defined cursors to abstract
-        data access so that users do not directly access tables or views, but
-        this solution has another impacts.
-       </simpara>
-      </listitem>
-     </itemizedlist>
-
-     <simpara>
-      Besides these, you benefit from logging queries either within your script
-      or by the database itself, if it supports logging. Obviously, the logging is 
unable
-      to prevent any harmful attempt, but it can be helpful to trace back which
-      application has been circumvented. The log is not useful by itself, but
-      through the information it contains. More detail is generally better than less.
-     </simpara>
-    </sect3>
-   </sect2>
-  </sect1>
-
-  <sect1 id="security.errors">
-   <title>Error Reporting</title>
-   <para>
-    With PHP security, there are two sides to error reporting. One is
-    beneficial to increasing security, the other is detrimental.
-   </para>
-   <para>
-    A standard attack tactic involves profiling a system by feeding
-    it improper data, and checking for the kinds, and contexts, of the
-    errors which are returned. This allows the system cracker to probe
-    for information about the server, to determine possible weaknesses.
-    For example, if an attacker had gleaned information about a page
-    based on a prior form submission, they may attempt to override
-    variables, or modify them:
-    <example>
-     <title>Attacking Variables with a custom HTML page</title>
-     <programlisting role="php">
-<![CDATA[
-<form method="post" action="attacktarget?username=badfoo&password=badfoo">
-<input type="hidden" name="username" value="badfoo" />
-<input type="hidden" name="password" value="badfoo" />
-</form>
-]]>
-     </programlisting>
-    </example>
-   </para>
-   <para>
-    The PHP errors which are normally returned can be quite helpful to a
-    developer who is trying to debug a script, indicating such things
-    as the function or file that failed, the PHP file it failed in,
-    and the line number which the failure occured in. This is all
-    information that can be exploited.  It is not uncommon for a php
-    developer to use <function>show_source</function>,
-    <function>highlight_string</function>, or
-    <function>highlight_file</function> as a debugging measure, but in
-    a live site, this can expose hidden variables, unchecked syntax,
-    and other dangerous information. Especially dangerous is running
-    code from known sources with built-in debugging handlers, or using
-    common debugging techniques. If the attacker can determine what
-    general technique you are using, they may try to brute-force a page,
-    by sending various common debugging strings:
-    <example>
-     <title>Exploiting common debugging variables</title>
-     <programlisting role="php">
-<![CDATA[
-<form method="post" action="attacktarget?errors=Y&amp;showerrors=1&amp;debug=1">
-<input type="hidden" name="errors" value="Y" />
-<input type="hidden" name="showerrors" value="1" />
-<input type="hidden" name="debug" value="1" />
-</form>
-]]>
-     </programlisting>
-    </example>
-   </para>
-   <para>
-    Regardless of the method of error handling, the ability to probe a
-    system for errors leads to providing an attacker with more
-    information.
-   </para>
-   <para>
-    For example, the very style of a generic PHP error indicates a system
-    is running PHP. If the attacker was looking at an .html page, and
-    wanted to probe for the back-end (to look for known weaknesses in
-    the system), by feeding it the wrong data they may be able to
-    determine that a system was built with PHP.
-   </para>
-   <para>
-    A function error can indicate whether a system may be running a
-    specific database engine, or give clues as to how a web page or
-    programmed or designed. This allows for deeper investigation into
-    open database ports, or to look for specific bugs or weaknesses
-    in a web page. By feeding different pieces of bad data, for example,
-    an attacker can determine the order of authentication in a script,
-    (from the line number errors) as well as probe for exploits that
-    may be exploited in different locations in the script.
-   </para>
-   <para>
-    A filesystem or general PHP error can indicate what permissions
-    the webserver has, as well as the structure and organization of
-    files on the web server. Developer written error code can aggravate
-    this problem, leading to easy exploitation of formerly "hidden"
-    information.
-   </para>
-   <para>
-    There are three major solutions to this issue. The first is to
-    scrutinize all functions, and attempt to compensate for the bulk
-    of the errors. The second is to disable error reporting entirely
-    on the running code. The third is to use PHP's custom error
-    handling functions to create your own error handler. Depending
-    on your security policy, you may find all three to be applicable
-    to your situation.
-   </para>
-   <para>
-    One way of catching this issue ahead of time is to make use of
-    PHP's own <function>error_reporting</function>, to help you
-    secure your code and find variable usage that may be dangerous.
-    By testing your code, prior to deployment, with E_ALL, you can
-    quickly find areas where your variables may be open to poisoning
-    or modification in other ways. Once you are ready for deployment,
-    by using E_NONE, you insulate your code from probing.
-    <example>
-     <title>Finding dangerous variables with E_ALL</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-if ($username) {  // Not initialized or checked before usage
-    $good_login = 1;
-}
-if ($good_login == 1) { // If above test fails, not initialized or checked before 
usage
-    readfile ("/highly/sensitive/data/index.html");
-}
-?>
-]]>
-     </programlisting>
-    </example>
-   </para>
-  </sect1>
-
-  <sect1 id="security.registerglobals">
-   <title>Using Register Globals</title>
-   <para>
-    Perhaps the most controversial change in PHP is when the default value
-    for the PHP directive <link linkend="ini.register-globals">
-    register_globals</link> went from ON to OFF in PHP 
-    <ulink url="&url.php.release4.2.0;">4.2.0</ulink>.  Reliance on this
-    directive was quite common and many people didn't even know it existed
-    and assumed it's just how PHP works.  This page will explain how one can
-    write insecure code with this directive but keep in mind that the
-    directive itself isn't insecure but rather it's the misuse of it.
-   </para>
-   <para>
-    When on, register_globals will inject (poison) your scripts will all
-    sorts of variables, like request variables from HTML forms.  This
-    coupled with the fact that PHP doesn't require variable initialization
-    means writing insecure code is that much easier.  It was a difficult
-    decision, but the PHP community decided to disable this directive by 
-    default.  When on, people use variables yet really don't know for sure
-    where they come from and can only assume.  Internal variables that are
-    defined in the script itself get mixed up with request data sent by
-    users and disabling register_globals changes this.  Let's demonstrate
-    with an example misuse of register_globals: 
-   </para>
-   <para>
-    <example>
-     <title>Example misuse with register_globals = on</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-// define $authorized = true only if user is authenticated
-if (authenticated_user()) {
-    $authorized = true;
-}
-
-// Because we didn't first initialize $authorized as false, this might be
-// defined through register_globals, like from GET auth.php?authorized=1 
-// So, anyone can be seen as authenticated!
-if ($authorized) {
-    include "/highly/sensitive/data.php";
-}
-?>
-]]>
-     </programlisting>
-    </example>
-   </para>
-   <para>
-    When register_globals = on, our logic above may be compromised.  When
-    off, <varname>$authorized</varname> can't be set via request so it'll
-    be fine, although it really is generally a good programming practice to 
-    initialize variables first.  For example, in our example above we might
-    have first done <literal>$authorized = false</literal>.  Doing this
-    first means our above code would work with register_globals on or off as 
-    users by default would be unauthorized.
-   </para>
-   <para>
-    Another example is that of <link linkend="ref.session">sessions</link>.
-    When register_globals = on, we could also use
-    <varname>$username</varname> in our example below but again you must
-    realize that <varname>$username</varname> could also come from other
-    means, such as GET (through the URL).  
-   </para>
-   <para>
-    <example>
-     <title>Example use of sessions with register_globals on or off</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-// We wouldn't know where $username came from but do know $_SESSION is 
-// for session data 
-if (isset($_SESSION['username'])) {
-    
-    echo "Hello <b>{$_SESSION['username']}</b>";
-
-} else {
-    
-    echo "Hello <b>Guest</b><br />";
-    echo "Would you like to login?";
-
-}
-?>
-]]>
-     </programlisting>
-    </example>
-   </para>
-   <para>
-    It's even possible to take preventative measures to warn when forging is
-    being attempted. If you know ahead of time exactly where a variable
-    should be coming from, you can check to see if the submitted data is
-    coming from an inappropriate kind of submission.  While it doesn't
-    guarantee that data has not been forged, it does require an attacker to
-    guess the right kind of forging.  If you don't care where the request
-    data comes from, you can use <varname>$_REQUEST</varname> as it contains
-    a mix of GET, POST and COOKIE data.  See also the manual section on
-    using <link linkend="language.variables.external">variables from outside
-    of PHP</link>. 
-   </para>
-   <para>
-    <example>
-     <title>Detecting simple variable poisoning</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-if (isset($_COOKIE['MAGIC_COOKIE'])) {
-    
-    // MAGIC_COOKIE comes from a cookie.
-    // Be sure to validate the cookie data!
-
-} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {
-   
-   mail("[EMAIL PROTECTED]", "Possible breakin attempt", $_SERVER['REMOTE_ADDR']);
-   echo "Security violation, admin has been alerted.";
-   exit;
-
-} else {
-   
-   // MAGIC_COOKIE isn't set through this REQUEST
-
-}
-?>
-]]>
-     </programlisting>
-    </example>
-   </para>
-   <para>
-    Of course, simply turning off register_globals does not mean your code
-    is secure.  For every piece of data that is submitted, it should also be
-    checked in other ways.  Always validate your user data and initialize
-    your variables!  To check for unitialized variables you may turn up
-    <function>error_reporting</function> to show
-    <constant>E_NOTICE</constant> level errors.
-   </para>
-   
-   &note.superglobals;
-
-  </sect1>
-
-
-  <sect1 id="security.variables">
-   <title>User Submitted Data</title>
-   <para>
-    The greatest weakness in many PHP programs is not inherent in the
-    language itself, but merely an issue of code not being written with
-    security in mind. For this reason, you should always take the time
-    to consider the implications of a given piece of code, to ascertain
-    the possible damage if an unexpected variable is submitted to it.
-    <example>
-     <title>Dangerous Variable Usage</title>
-     <programlisting role="php">
-<![CDATA[
-<?php
-// remove a file from the user's home directory... or maybe
-// somebody else's?
-unlink ($evil_var);
-
-// Write logging of their access... or maybe an /etc/passwd entry?
-fputs ($fp, $evil_var);
-
-// Execute something trivial.. or rm -rf *?
-system ($evil_var);
-exec ($evil_var);
-
-?>
-]]>
-     </programlisting>
-    </example>
-    You should always carefully examine your code to make sure that any
-    variables being submitted from a web browser are being properly
-    checked, and ask yourself the following questions:
-    <itemizedlist>
-     <listitem>
-      <simpara>
-       Will this script only affect the intended files?
-      </simpara>
-     </listitem>
-     <listitem>
-      <simpara>
-       Can unusual or undesirable data be acted upon?
-      </simpara>
-     </listitem>
-     <listitem>
-     <simpara>
-       Can this script be used in unintended ways?
-      </simpara>
-     </listitem>
-     <listitem>
-      <simpara>
-       Can this be used in conjunction with other scripts in a negative
-       manner?
-      </simpara>
-     </listitem>
-     <listitem>
-      <simpara>
-       Will any transactions be adequately logged?
-      </simpara>
-     </listitem>
-    </itemizedlist>
-    By adequately asking these questions while writing the script,
-    rather than later, you prevent an unfortunate re-write when you
-    need to increase your security. By starting out with this mindset,
-    you won't guarantee the security of your system, but you can help
-    improve it.
-   </para>
-   <para>
-    You may also want to consider turning off register_globals,
-    magic_quotes, or other convenience settings which may confuse
-    you as to the validity, source, or value of a given variable.
-    Working with PHP in error_reporting(E_ALL) mode can also help warn
-    you about variables being used before they are checked or
-    initialized (so you can prevent unusual data from being
-    operated upon).
-   </para>
-  </sect1>
-
-  <sect1 id="security.hiding">
-   <title>Hiding PHP</title>
-   <para>
-    In general, security by obscurity is one of the weakest forms of security.
-    But in some cases, every little bit of extra security is desirable.
-   </para>
-   <para>
-    A few simple techniques can help to hide PHP, possibly slowing
-    down an attacker who is attempting to discover weaknesses in your
-    system. By setting expose_php = off in your &php.ini; file, you
-    reduce the amount of information available to them.
-   </para>
-   <para>
-    Another tactic is to configure web servers such as apache to
-    parse different filetypes through PHP, either with an &htaccess;
-    directive, or in the apache configuration file itself. You can
-    then use misleading file extensions:
-    <example>
-     <title>Hiding PHP as another language</title>
-     <programlisting role="apache-conf">
-<![CDATA[
-# Make PHP code look like other code types
-AddType application/x-httpd-php .asp .py .pl
-]]>
-     </programlisting>
-    </example>
-    Or obscure it completely:
-    <example>
-     <title>Using unknown types for PHP extensions</title>
-     <programlisting role="apache-conf">
-<![CDATA[
-# Make PHP code look like unknown types
-AddType application/x-httpd-php .bop .foo .133t
-]]>
-     </programlisting>
-    </example>
-    Or hide it as HTML code, which has a slight performance hit because
-    all HTML will be parsed through the PHP engine:
-    <example>
-     <title>Using HTML types for PHP extensions</title>
-     <programlisting role="apache-conf">
-<![CDATA[
-# Make all PHP code look like HTML
-AddType application/x-httpd-php .htm .html
-]]>
-     </programlisting>
-    </example>
-    For this to work effectively, you must rename your PHP files with
-    the above extensions. While it is a form of security through
-    obscurity, it's a minor preventative measure with few drawbacks.
-   </para>
-  </sect1>
-
-  <sect1 id="security.current">
-   <title>Keeping Current</title>
-   <simpara>
-    PHP, like any other large system, is under constant scrutiny and
-    improvement. Each new version will often include both major and
-    minor changes to enhance and repair security flaws, configuration
-    mishaps, and other issues that will affect the overall security
-    and stability of your system.
-   </simpara>
-   <simpara>
-    Like other system-level scripting languages and programs, the best
-    approach is to update often, and maintain awareness of the latest
-    versions and their changes.
-   </simpara>
-  </sect1>
+  &security.general;
+  &security.cgi-bin;
+  &security.apache;
+  &security.filesystem;
+  &security.database;
+  &security.errors;
+  &security.globals;
+  &security.variables;
+  &security.hiding;
+  &security.current;
  </chapter>
 
 <!-- Keep this comment at the end of the file

Reply via email to