Other Security Features


In addition to Safe Mode, PHP provides a number of functions that allow you to place restrictions on the features available to PHP.

Hiding PHP

You can use the expose_php directive in php.ini to prevent the presence of PHP being reported by the web server, as follows:

 expose_php = On 

By using this setting, you can discourage automated scripts from trying to attack your web server. Usually, the HTTP headers contain a line that looks like the following:

 Server: Apache/1.3.33 (Unix) PHP/5.0.3 mod_ssl/2.8.16 OpenSSL/0.9.7c 

With the expose_php directive enabled, the PHP version is not included in this header.

Of course, the .php file extension is a giveaway to visitors that PHP is in use on a website. If you want to use a totally different file extension, you need to first find the following line in httpd.conf:

 AddType application/x-httpd .php 

Then you need to change .php to any file extension you like. You can specify any number of file extensions, separated by spaces. To have PHP parse .html and .htm files so there is no indication that a server-side language is being used at all, you can use the following directive:

 AddType application/x-httpd .html .htm 

Parsing HTML Configuring your web server to parse all HTML files with PHP may be convenient, but a small performance hit is involved because the PHP parser needs to fire up even if there is no server-side code in a web page.

By using a different file extension for static pages, you can eliminate the need for PHP to be involved where it is not necessary.


Filesystem Security

Safe Mode restricts filesystem access only to files owned by the script owner, and you can use the open_basedir directive to specify the directory in which a file must reside. If you specify a directory, PHP will refuse any attempt to access a file that is not in that directory or its subdirectory tree. The open_basedir directive works independently of Safe Mode.

To restrict filesystem access on your web server to only the /tmp directory, you use the following directive:

 open_basedir = /tmp 

Function Access Control

You can use the disable_functions directive to specify a comma-delimited list of function names that will be disabled in the PHP language. This setting works independently of Safe Mode.

To disable the dl function without turning on Safe Mode, you use the following directive:

 disable_functions = dl 

You can also disable access to classes by using the disable_classes directive in the same way.

Database Security

You learned in Lesson 18, "Host Program Execution," how a malicious user might try to run an arbitrary host command on your system, and that you can use the escapeshellcmd function to prevent this kind of abuse.

A similar situation applies to database use through PHP. Suppose your script contains the following lines to execute a MySQL query based on a form value:

 $sql = "UPDATE mytable SET col1 = " . $_POST["value"] . "         WHERE col2 = 'somevalue'"; $res = mysql_query($sql, $db); 

You are expecting $_POST["value"] to contain an integer value to update the value of column col1. However, a malicious user could enter a semicolon in the form input field, followed by any SQL statement he or she wants to execute.

For instance, suppose the following is the value of $_POST["value"]:

 0; INSERT INTO admin_users (username, password) VALUES ('me', 'mypassword'); 

The SQL executed would then look like the following (the statements are shown here on separate lines for clarity):

 UPDATE mytable SET col1 = 0; INSERT INTO admin_users (username, password) VALUES ('me', 'mypassword'); WHERE col2 = 'somevalue'; 

This is clearly a bad situation! The first statement updates the value of col1 for all rows in mytable. This will be an inconvenience, but the second statement creates a more serious problemthe user has been able to execute an INSERT statement that creates a new administrator login. The third statement is rubbish, but by the time the SQL parser reaches that statement and throws an error, the damage has been done. This type of attack is known as SQL injection.

Of course, for SQL injection to be a serious threat, the user must understand a little about your database structure. In this example, the attacker is aware that you have a table called admin_users, that it contains fields named username and password, and that the password is stored unencrypted.

A visitor to your website would not generally know such information about a database you built yourself. However, if your website includes open-source componentsperhaps you have used a freeware discussion board programthe table definitions for at least some of your database are accessible to users.

Furthermore, if your script produces output whenever a query fails, this could reveal important details about your database structure. On a production website, you should consider setting display_errors to off and using log_errors to write warnings and error messages to a file instead.

Database Permissions It is vital that the database connection from your script be made by a database user who has only just enough access rights to perform the job.

You should certainly never connect as an administrator from a script. If you did, an attacker would be able to gain full access to your database and others on the same server. Attackers will also be able to run the GRANT or CREATE USER command to give themselves full access outside the confines of your script!


To prevent the possibility of a SQL injection attack, you must ensure that user-submitted data that forms part of a query cannot be used to interrupt the SQL statement that you intend to execute.

The previous example shows an integer value being updated. If this were a string value enclosed in single quotes, the attacker would need to submit a closing quote before the semicolon and then the SQL statement. However, when magic_quotes_gpc is turned on, a quotation mark submitted via a web form will be automatically delimited.

To be absolutely sure that form-submitted values are not vulnerable to SQL injection attacks, you should always ensure that the data received is appropriate. If your query expects a numeric value, you should test the form value with is_numeric or use settype to convert it to a number, removing any characters that are designed to fool SQL.

If you are working with several user-submitted values in one SQL statement, you can use the sprintf function to build a SQL statement string, using format characters that indicate the data type of each value. The following is an example:

 $sql = sprintf("UPDATE mytable SET col1 = %d                  WHERE col2 = '%s'",                  $_POST["number"],                  mysql_escape_string($_POST["string"])); 

The preceding example assumes that a MySQL database is being used, so the string value is passed to mysql_escape_string. For other databases, you should ensure that quote characters are adequately delimited, by using addslashes or another suitable method.



    Sams Teach Yourself PHP in 10 Minutes
    Sams Teach Yourself PHP in 10 Minutes
    ISBN: 0672327627
    EAN: 2147483647
    Year: 2005
    Pages: 151
    Authors: Chris Newman

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net