Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Apress.Pro.Drupal.7.Development.3rd.Edition.Dec.2010.pdf
Скачиваний:
73
Добавлен:
14.03.2016
Размер:
12.64 Mб
Скачать

CHAPTER 21 WRITING SECURE CODE

The first two examples try to manipulate the file path by including the two dots that indicate a parent directory to the underlying operating system. In the last example, the programmer attempts to execute a shell command and has included a semicolon so that after the shell command runs, an additional command will run that will make settings.php readable and thus reveal the database username and password. All of the preceding examples are hoping that file permissions are set incorrectly, and that the web server actually has write access to directories other than the file system path.

Whenever you are using file paths, a call to file_valid_uri() is in order, like this:

if (!file_valid_uri($uri) {

// Abort! File URI is not what was expected!

}

The file_valid_uri() function will find out whether the URI has a valid scheme for file operations. In general, you probably don’t want the Next Great File Management Module to be your first Drupal

project. Instead, study existing file-related modules that have been around for a while.

Encoding Mail Headers

When writing any code that takes user input and builds it into an e-mail message, consider the following two facts:

E-mail headers are separated by line feeds (only line feeds that aren’t followed by a space or tab are treated as header separators).

Users can inject their own headers in the body of the e-mail if you don’t check that their input is free of line feeds.

For example, say you expect the user to enter a subject for his or her message, and the user enters a string interspersed by escaped line feed (%0A) and space (%20) characters:

Have a nice day%0ABcc:spamtarget@example.com%0A%0AL0w%20c0st%20mortgage!

The result would be as follows:

Subject: Have a nice day

Bcc: spamtarget@example.com

L0w c0st mortgage!

...

For that reason, Drupal’s built-in mail function drupal_mail() in includes/mail.inc runs all headers through mime_header_encode() to sanitize headers. Any nonprintable characters will be encoded into ASCII printable characters according to RFC 2047, and thus neutralized. This involves prefixing the character with =?UTF-8?B? and then printing the Base64-encoded character plus ?=.

You’re encouraged to use drupal_mail(); if you choose not to, you’ll have to make the mime_header_encode() calls yourself.

481

CHAPTER 21 WRITING SECURE CODE

Files for Production Environments

Not all files included in the distribution of Drupal are necessary for production sites. For example, making the CHANGELOG.txt file available on a production site means that anyone on the Web can see what version of Drupal you are running (of course, the black hats have other ways of detecting that you are running Drupal; see www.lullabot.com/articles/is-site-running-drupal). Table 21-3 lists the files and/or directories that are necessary for Drupal to function after it has been installed; the others can be removed from a production site (keep a copy, though!). Alternatively, read access can be denied to the web server.

Table 21-3. Files and Directories That Are Necessary for Drupal to Function

File/Directory

Purpose

 

 

.htaccess

Security, clean URL, and caching support on Apache

cron.php

Allows regularly scheduled tasks to run

includes/

Function libraries

index.php

Main entry point for Drupal requests

misc/

JavaScript and graphics

modules/

Core modules

robots.txt

Prevents well-behaved robots from hammering your site

sites/

Site-specific modules, themes, and files

themes/

Core themes

xmlrpc.php

XML-RPC endpoint; necessary only if your site will receive incoming XML-RPC

 

requests

authorize.php

Administrative script for running authorized file operations

 

 

SSL Support

By default, Drupal handles user logins in plain text over HTTP. However, Drupal will happily run over HTTPS if your web server supports it. No modification to Drupal is required.

482

CHAPTER 21 WRITING SECURE CODE

Stand-Alone PHP

Occasionally, you might need to write a stand-alone .php file instead of incorporating the code into a Drupal module. When you do, be sure to keep security implications in mind.

Note The following code is for instructional purposes. The best approach is to leverage the power of Drush (http://drush.ws), a command line shell and scripting interface for Drupal. Drush automatically performs a full bootstrap of Drupal before it executes your script. There’s no need to include the bootstrap code in your PHP file, which eliminates the security risks outlined in the sample code that follows.

Suppose, when you were testing your web site, you wrote some quick and dirty code to insert users into the database so you could test performance with many users. Perhaps you called it testing.php and put it at the root of your Drupal site, next to index.php. Then you bookmarked it in your browser, and every time you wanted a fresh user table, you selected the bookmark:

<?php

/**

* This script generates users for testing purposes. */

//These lines are all that is needed to have full

//access to Drupal's functionality.

include_once 'includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

db_delete('users') ->condition('uid', '1', '>') ->execute();

for ($i =

2; $i <= 5000; $i++) {

$name =

$i;

$pass

=

md5(user_password());

$mail

=

$name .'@localhost';

$status

= 1;

db_insert('users')

->fields(array('name' => $name, 'pass' => $pass, 'mail' => $mail, 'status'

=> $status, 'created' => time(), 'access' => time())), ->execute();

}

print t('Users have been created.');

483

CHAPTER 21 WRITING SECURE CODE

That’s useful for testing, but imagine what would happen if you forgot that the script was there and the script made it onto your production site! Anyone who found the URL to your script (http://example.com/testing.php) could delete your users with a single request. That’s why it’s important, even in quick one-off scripts, to include a security check, as follows:

<?php

/**

* This script generates users for testing purposes. */

//These lines are all that is needed to have full

//access to Drupal's functionality.

include_once 'includes/bootstrap.inc'; drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);

// security check; only the site administrator may execute global $user;

if ($user->uid != 1) {

print t('Not authorized.'); exit();

}

db_delete('users') ->condition('uid', '1', '>') ->execute();

for ($i =

2; $i <= 10; $i++) {

$name =

$i;

$pass

=

md5(user_password());

$mail

=

$name .'@localhost';

$status

= 1;

db_insert('users')

->fields(array('name' => $name, 'pass' => $pass, 'mail' => $mail, 'status'

=> $status, 'created' => time(), 'access' => time())), ->execute();

}

print t('Users have been created.');

Here are two take-home lessons:

Write security checking even into quickly written scripts, preferably working from a template that includes the necessary code.

Remember that an important part of deployment is to remove or disable testing code.

484

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]