user.module via the admin/access menu produces a form to edit, for each permission defined for each module, which role is enabled. If one permission name (perm1) is a substring of another permission name (perm2), then if a role is enabled for perm2 it appears to be enabled also for perm1 in the form, and if the form is saved, also in the DB.

The patch is simple (also included as attachment):

--- user.module~        2006-08-12 07:04:19.000000000 +0000
+++ user.module 2006-09-01 15:48:58.000000000 +0000
@@ -1791,7 +1791,8 @@
         $form['permission'][$perm] = array('#type' => 'markup', '#value' => t($perm));
         foreach ($role_names as $rid => $name) {
           // Builds arrays for checked boxes for each role
-          if (strstr($role_permissions[$rid], $perm)) {
+          // if (preg_match($role_permissions[$rid], $perm)) {
+          if (preg_match("/(^|,\s*)$perm(,|$)/", $role_permissions[$rid])) {
             $status[$rid][] = $perm;
           }
         }

$perm is a permission string, $role_permissions[$rid] is a comma+space separated list of permissions enabled for role $rid. The strstr check also matches perm1 if perm2 belongs to the list, preg_match with the proper pattern doesn't.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

alusiani’s picture

FileSize
587 bytes

I made an error on including the patch as attachment, I correct it here

bjaspan’s picture

Status: Active » Needs work

I reviewed this patch and agree with your approach. This problem still exists in 5.0, too. However,

(1) You should remove the commented-out call to preg_match for cleanliness and
(2) I think it would be better to use the word-boundary assertion (e.g. "/\\b$perm\\b/") instead of the conditional expression you used.

Zen’s picture

Version: 4.7.3 » 5.x-dev

As per bjaspan, this occurs in 5. Therefore, please reroll for 5 and then backport to 4.7 once fixed.

Thanks,
-K

moshe weitzman’s picture

Priority: Critical » Normal

this is a rare event, so downgrading. i'm even tempted to downgrade to minor ...

Steven’s picture

Regular expression word boundaries are unreliable. They match e.g. in the middle of "xml-rpc".

dww’s picture

Assigned: Unassigned » dww
Status: Needs work » Needs review
FileSize
1.19 KB

IMHO, this is is almost critical, since it *really* confuses the hell out of the UI for permissions and can end up leading to permissions being granted that the admin didn't really intend. :( however, i won't get in a pushing match over the priority.

i discussed this with Heine (when i found this myself, i wanted to check with him to see if he thought it was a security issue or if i should post an issue here, and then searched the queue to find this). we decided that the simplest solution is to mimic the behavior of user_access(), which basically always appends a , to the end of the list of permission names, and when searching always searches for $perm .','. it's a bit of a hack, but it's simple, fast, consistent with other parts of core, and it works. ;)

attached patch for 5.x. 4.7.x patch coming next.

dww’s picture

4.7.x patch. i took the liberty of removing a line of dead code (an array definition that's not used anywhere in the function) that was causing the 5.x patch to fail to apply cleanly.

dww’s picture

even better: use strpos() instead of strstr():
- faster and uses less memory
- consistent with user_access()

5.x version

dww’s picture

improved 4.7.x version

bdragon’s picture

Status: Needs review » Reviewed & tested by the community

#8, #9: Desk checked. Sane. No other lines reuse the variable in question. +1 from me.

The line of dead code has been dead since its creation with rev. 1.60, over 4 years ago.

Dries’s picture

Version: 5.x-dev » 4.7.x-dev

Committed this patch to CVS HEAD and DRUPAL-5. Needs fixing in DRUPAL-4-7 as well.

killes@www.drop.org’s picture

Status: Reviewed & tested by the community » Fixed

backported

Anonymous’s picture

Status: Fixed » Closed (fixed)