Drupal ImageCache 6.x-2.0-beta9 Multiple XSS Vulnerability

30 November -0001

Drupal (http://drupal.org) is a robust content management system (CMS) written in PHP and MySQL that provides extensibility through various third party modules. The ImageCache module (http://drupal.org/project/imagecache) "allows you to setup presets for image processing. If an ImageCache derivative doesn't exist the web server's rewrite rules will pass the request to Drupal which in turn hands it off to ImageCache to dynamically generate the file."

The ImageCache module contains several cross site scripting vulnerabilities because it does not properly sanitize output of action preset values before display.

Systems affected:

Drupal 6.13 with ImageCache 6.x-2.0-beta9 was tested and shown to be vulnerable. Drupal 5.19 with ImageCache 5.x-2.4 was tested and shown to be vulnerable.

Impact:

XSS vulnerabilities may expose site administrative accounts to compromise which could lead to web server process compromise.

Mitigating factors:

The ImageCache module must be installed. To carry out an role name XSS exploit against the ImageCache module the attacker must be able to inject malicious content into action presets, which is possible for authenticated users with the 'administer imagecache' permission. Users viewing the malicious preset values are susceptible to the XSS attack.

Proof of Concept:

  1. Install Drupal 6.13.
  2. Install and enable the ImageCache module 6.x-2.0-beta9
  3. Click on 'Administer' -> 'Site Building' -> 'ImageCache'
  4. Enter a new preset name and click 'Create New Preset'
  5. On the resulting screen click 'Add Crop' under the Actions
  6. On the 'Add imagecache_crop' page enter "<script>alert('xss');</script>" in the width, height, x offset and y offset textareas.
  7. Click 'Add Action' button
  8. Observe JavaScript alerts

This vulnerability exists in the 'Add Deprecated Scale', 'Add Resize', 'Add Rotate', 'Add Scale', 'Add Scale And Crop' and 'Add Sharpen' actions as well.

Because the input values can be closed in scope to alphanumeric and percent (%) signs, ideally the input should be scrubbed of any characters that fall outside of this range. The patch below only sanitizes output, rather than limiting input to known good values.

Patch

Applying the following patch to a Drupal 6 installation mitigates these threats.

# diff -up imagecache imagecache_fixed/
diff -up imagecache/imagecache_actions.inc
imagecache_fixed/imagecache_actions.inc
- --- imagecache/imagecache_actions.inc   2009-04-16 22:57:25.000000000
-0400
+++ imagecache_fixed/imagecache_actions.inc     2009-08-03
12:34:11.693834523 -0400
@@ -90,6 +90,7 @@ function imagecache_deprecated_scale_for

 function theme_imagecache_deprecated_scale($element) {
   $data = $element['#value'];
+  $data = array_map("check_plain", $data);
   $options = array('inside' => t('Inside dimensions'), 'outside' =>
t('Outside dimensions'));
   return 'width: '. $data['width'] .', height: '. $data['height'] .',
fit: '. $options[$data['fit']];
 }
@@ -152,6 +153,7 @@ function imagecache_crop_form($data) {

 function theme_imagecache_crop($element) {
   $data = $element['#value'];
+  $data = array_map("check_plain", $data);
   return 'width: '. $data['width'] .', height: '. $data['height'] .',
xoffset: '. $data['xoffset'] .', yoffset: '. $data['yoffset'];
 }

@@ -212,8 +214,9 @@ function imagecache_rotate_form($data) {
 }

 function theme_imagecache_rotate($element) {
- -  $output = t('degrees:') .' '. $element['#value']['degrees'] .', ';
+  $output = t('degrees:') .' '.
check_plain($element['#value']['degrees']) .', ';
   $output .= t('randomize:') .' '. (($element['#value']['random']) ?
t('Yes') : t('No')) .', ';
+  $element['#value']['bgcolor'] =
check_plain($element['#value']['bgcolor']);
   $output .= t('background:') .' '.
strlen(trim($element['#value']['bgcolor'])) ?
$element['#value']['bgcolor'] : t('Transparent/white');
   return $output;
 }
@@ -281,10 +284,10 @@ function imagecache_sharpen_form($data)
 }

 function theme_imagecache_sharpen($element) {
- -  $output = t('radius:') .' '. $element['#value']['radius'] .', ';
- -  $output .= t('sigma:') .' '. $element['#value']['sigma'] .', ';
- -  $output .= t('amount:') .' '. $element['#value']['amount'] .', ';
- -  $output .= t('threshold:') .' '. $element['#value']['threshold'] ;
+  $output = t('radius:') .' '.
check_plain($element['#value']['radius']) .', ';
+  $output .= t('sigma:') .' '. check_plain($element['#value']['sigma'])
.', ';
+  $output .= t('amount:') .' '.
check_plain($element['#value']['amount']) .', ';
+  $output .= t('threshold:') .' '.
check_plain($element['#value']['threshold']) ;
   return $output;
 }

diff -up imagecache/imagecache.module imagecache_fixed/imagecache.module
- --- imagecache/imagecache.module        2009-04-13 20:01:21.000000000
-0400
+++ imagecache_fixed/imagecache.module  2009-08-03 12:28:18.496842922 -0400
@@ -829,6 +829,7 @@ function imagecache_resize_form($action)

 function theme_imagecache_resize($element) {
   $data = $element['#value'];
+  $data = array_map("check_plain", $data);
   return 'width: '. $data['width'] .', height: '. $data['height'];
 }

Vendor Response

Install the latest version. http://drupal.org/node/554084.