Drupal 6 Profile (core) Module XSS Vulnerability
Description of Vulnerability:
Drupal (http://drupal.org) is a robust content management system (CMS) written in PHP and MySQL that provides extensibility through hundreds of third party modules. The profile module is provided as part of the Drupal 6 core modules and contains several arbitrary script injection vulnerabilities that can allow users with the 'administer users' permission to inject arbitrary HTML into category names and explanations. This vulnerability was discovered in Drupal 7 and is public (http://drupal.org/node/611532) thus this report serves only to call out the vulnerability in Drupal 6.
Systems affected:
Drupal 6.15 was tested and shown to be vulnerable
Mitigating factors:
Attacker must have 'administer users' and 'access administration pages" permissions in order to exploit this vulnerability.
Proof of concept:
- Install Drupal 6.15.
- Enable the profile module from Administer -> Site building -> Modules
- Go to Administer -> User management -> Profiles and click on 'single-line textfield'
- Enter "<script>alert('xss1');</script>" for Category
- Enter "<script>alert('xss2');</script>" for Explanation
- Fill in arbitrary values for other fields and click 'Save field' button
- Observe the category XSS on the resulting page
- Click Administer -> Users, and select a user and click the 'Edit' link
- Click the "<script>alert('xss1');</script>" tab at the top of the form
- Observe the second XSS on the resulting page.
Drupal 6 Patch
Applying the following patch mitigates these threats.
--- drupal-6.15/modules/profile/profile.admin.inc 2008-10-16 08:43:08.000000000 -0400 +++ drupal-6.15.patched/modules/profile/profile.admin.inc 2010-03-03 14:33:44.740024567 -0500 @@ -25,7 +25,7 @@ function profile_admin_overview() { $form[$field->fid]['name'] = array('#value' => check_plain($field->name)); $form[$field->fid]['title'] = array('#value' => check_plain($field->title)); $form[$field->fid]['type'] = array('#value' => $field->type); - $form[$field->fid]['category'] = array('#type' => 'select', '#default_value' => $field->category, '#options' => array()); + $form[$field->fid]['category'] = array('#type' => 'select', '#default_value' => check_plain($field->category), '#options' => array()); $form[$field->fid]['weight'] = array('#type' => 'weight', '#default_value' => $field->weight); $form[$field->fid]['edit'] = array('#value' => l(t('edit'), "admin/user/profile/edit/$field->fid")); $form[$field->fid]['delete'] = array('#value' => l(t('delete'), "admin/user/profile/delete/$field->fid")); diff -up drupal-6.15.new/modules/profile/profile.module drupal-6.15.clean/modules/profile/profile.module --- drupal-6.15.new/modules/profile/profile.module 2009-01-12 05:09:19.000000000 -0500 +++ drupal-6.15.clean/modules/profile/profile.module 2010-03-03 14:32:54.749038065 -0500 @@ -341,7 +341,7 @@ function _profile_form_explanation($fiel $output .= ' '. t('The content of this field is kept private and will not be shown publicly.'); } - return $output; + return check_plain($output); } function profile_form_profile($edit, $user, $category, $register = FALSE) {