SA-2007-018 (26 July 2007) - Multiple cross site scripting vulnerabilities

  • Advisory ID: DRUPAL-SA-2007-018
  • Project: Drupal core
  • Version: 4.6.x, 4.7.x, 5.x
  • Date: 2007-July-26
  • Security risk: Moderately critical
  • Exploitable from: Remote
  • Vulnerability: Multiple cross site scripting vulnerabilities

Some server variables are not escaped consistently. When a malicious user is able to entice a victim to visit a specially crafted link or webpage, arbitrary HTML and script code can be injected and executed in the context of the victim's session on the targeted website.

Custom content type names are not escaped consistently. A malicious user with the 'administer content types' permission would be able to inject and execute arbitrary HTML and script code on the website. Revoking the 'administer content types' permission provides an immediate workaround.

The official announcement for Drupal 4.7 and 5.1 is here, and the official patch for 4.7.6 is here.

Older versions of the Drupal 4.7 branch are subject to the same vulnerability, but the official patch does not apply cleanly against them. Below you will find a slightly altered patch which will work against 4.7.3 and other older versions of 4.7.x without rejected changes:

Considerations for Drupal 4.6

The server variables $_SERVER['PHP_SELF'] and $_SERVER['HTTP_HOST'] can be modified by an attacker to contain unsafe characters. This patch removes those vulnerabilities from Drupal 4.6 core files, although some contributed modules may also be using those variables unsafely, and should be checked. As in the official patch, this can be fixed by using $_SERVER['SCRIPT_NAME'] instead of $_SERVER['PHP_SELF'] and by calling check_plain() on the value of $_SERVER['HTTP_HOST']. Drupal 4.6 must be patched against this vulnerability.

Custom content type names are handled differently in 4.6, mostly because the entire forms system was rewritten in 4.7. The 4.6 version of these files already calls check_plain() for these strings.

A backport of the official patches for Drupal 4.6 is available here:

An explanation of why we believe this patch is sufficient follows:

includes/bootstrap.inc
Drupal 4.6 requires $base_url to be set in settings.php and does not attempt to deduce a value from $_SERVER['HTTP_HOST'] if this is not set, so this part of the patch for 4.7 is not relevant.
includes/common.inc
This file does not need to be patched as in 4.6 it contains no reference to $_SERVER['PHP_SELF'].
modules/profile.module
This file does not need to be patched since check_plain() is already called for profile field titles, using the old forms system.
settings.php
This file does not need to be patched because in 4.6 it doesn't use $_SERVER['HTTP_HOST'] (since session.cookie_domain isn't set by default).

You may also be interested in further discussion of the problems with PHP_SELF and with HTTP_HOST.