If you add a javascript as new name of a role, this will be executed into admin/user/permission page.
I assume this is not a security hole because it's inside admin area.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

pwolanin’s picture

Version: 6.4 » 7.x-dev

This should be fixed, but is not really a security hole - to add new roles requires 'administer permissions' which already means you essentially can escalate your own permissions without limit.

pwolanin’s picture

Status: Active » Needs review
FileSize
1.55 KB

Catching it in the user_roles() function also gets most places it's displayed - but might lead to double-encoding.

pwolanin’s picture

Issue tags: +Security improvements
pwolanin’s picture

Category: bug » task
Status: Needs review » Needs work

This will break any select lists using the output of the user_roles() function, so guess we would need to track down uses.

However, it would perhaps make more sense to just validate on input as we do for translations.

dww’s picture

Right. We're back to the evil checkboxes are output unescaped, while select lists are escaped by FAPI. Ugh. Given that, I think we really do have to continue to output potentially malicious text from user_roles(), and check the call sites 1-by-1 to fix this.

I think it's reasonable to consider validation-on-input, too, but then it seems like we need a DB update to check for existing roles that aren't valid. Not sure what exactly to do with them during the DB update in that case. :( Given that, we should probably stick with escape-on-output...

While we're grepping, we should also make sure no one does anything stupid with $user->roles directly. The hunk in user_edit() is the only spot I can think of where we do anything with that, but there might be others, so we should check.

I'm *really* tempted to call this "minor". If you can't trust the users that have 'administer permissions', you're already in deep trouble.

greggles’s picture

Is check_plain the right filter here? The issue we're trying to fix is XSS. Why not filter_xss_admin?

Validation on input goes against our overall filtering practice. It also won't save us when some contrib/install profile creates a role name based on user input. We filter on output.

Heine’s picture

Because rolenames are plaintext (would you expect tags in them? (no) Ampersands ? (yes)), they need to be check_plained to get even valid HTML.

Heine’s picture

Also from Handle text in a secure fashion:

Plain-text
This is simple text without any markup. What the user entered is displayed exactly on screen as is, and is not interpreted in any form. This is generally the format used for single-line text fields.

When outputting plain-text, you need to pass it through check_plain() before it can be put inside HTML. This will convert quotes, ampersands and angle brackets into entities, causing the string to be shown literally on screen in the browser.

David_Rothstein’s picture

Category: task » bug
Status: Needs work » Needs review
FileSize
4.77 KB

I think this patch might get all of them.

And this really should be considered a bug, since it prevents e.g. contrib modules from (safely) allowing less-privileged administrators to edit the role names -- which is something they might reasonably want to do.

meba’s picture

Priority: Normal » Critical

Is this critical for D7 stable? I guess so...

Jody Lynn’s picture

Priority: Critical » Normal

This does not seem critical, as it's a 'root user can hack himself' type of vulnerability.

coltrane’s picture

Let's just get this fixed and committed.

+++ modules/block/block.admin.inc	21 Mar 2010 20:14:37 -0000
@@ -313,7 +313,7 @@ function block_admin_configure($form, &$
+  $role_options = array_map('check_plain', db_query('SELECT rid, name FROM {role} ORDER BY name')->fetchAllKeyed());

Couldn't we use user_roles() here instead of querying directly?

coltrane’s picture

Here's a reroll because part of the patch no longer applied. I'm also trying user_roles() instead of the direct query.

David_Rothstein’s picture

Looks good to me - that direct database query was a preexisting bug (a bug because its failure to use the API means the roles were presented in the wrong order), but might as well fix it here too.

RTBC from my point of view, but I wrote most of it :) I hope in the intervening months there weren't any new instances where role names are displayed (probably not, but I remember them being a pain to search for).

webchick’s picture

Status: Needs review » Fixed

I can't think of any new ones either. This looks like a good hardening improvement.

Committed to HEAD. Thanks!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

klausi’s picture

Version: 7.x-dev » 6.x-dev
Status: Closed (fixed) » Patch (to be ported)

OMG, this was never backported to D6? How should I explain to new contributors that they need to sanitize role names before printing them if even D6 core doesn't handle it properly?

greggles’s picture

It probably should be done, yes, but per http://drupal.org/security-advisory-policy it's not a priority.

As for the review process, tell them it's still right to learn the best practices even if core doesn't follow them.

Albert Volkman’s picture

Status: Patch (to be ported) » Needs review
FileSize
4.13 KB

D6 backport!

klausi’s picture

Status: Needs review » Needs work
+++ b/modules/filter/filter.module
@@ -323,6 +323,26 @@ function filter_formats($index = NULL) {
+function filter_get_roles_by_format($format) {

please don't introduce new functions, we should only do sanitization in this patch to comply with Drupal security standards. Also I think it is too late in the D6 release cycle to add a function just like that.

Albert Volkman’s picture

Status: Needs work » Needs review
FileSize
3.4 KB

Gotcha, wasn't sure how to go about that. I've re-implemented the logic directly in the function. Does this look better?

klausi’s picture

Status: Needs review » Needs work

Do not add any logic, just sanitize the role names and leave everything else as is, I would say. Do not touch the DB queries, do not replace anything with user_roles(), just plain sanitization before outputting role names.

David_Rothstein’s picture

-      // Prepare a roles array with roles that may access the filter.
-      if (strstr($format->roles, ",$rid,")) {
-        $roles[] = $name;
-      }
+    $format_roles = array();
+    $permission = filter_permission_name($format);
+
+    if ($format->format == filter_fallback_format()) {

Those filter functions don't exist in Drupal 6, so they can't be used here.

Isn't it possible to just run check_plain() on the content of $roles, without adding any extra code?

darktygur-1’s picture

Status: Needs work » Needs review
FileSize
3.91 KB

Really surprised this hasn't been fixed already. While this isn't really a security problem, if nothing says you can't enter special characters then the site should really be able to properly display them. I just ran across this testing a contrib module that wasn't sanitizing role names. I entered an unsafe role name and noticed that the admin/user/roles page wasn't even sanitizing them. Eventually I came across this issue.

This patch is based on the one from #21. No extra logic in this one, just check_plain() calls. Also, the previous patch missed a spot - theme_user_admin_new_role(), ironically affecting the page where I first noticed this bug. Another difference is in user_admin_account() - I made sure to call check_plain() after sorting rather than before, because sorting sanitized versions of role names gives slightly different results if they actually have special characters.

I spent far too much time deciding whether I wanted to make it call check_plain() on the names for anonymous user and authenticated user roles in theme_user_admin_new_role(). I don't think it matters either way. Sanitizing them accounts for the infinitesimally small chance that a module (or an administrator wielding phpMyAdmin) would attempt to rename those roles to something with special characters. Leaving it out saves just two function calls on just one admin page. I chose to go for it, but I don't care if someone else chooses to remove the second check_plain() I added in that function.

greggles’s picture

Status: Needs review » Reviewed & tested by the community

Would be nice to finish this off.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 24: user_roles_check_plain-316136-24-d6.patch, failed testing.

Status: Needs work » Closed (outdated)

Automatically closed because Drupal 6 is no longer supported. If the issue verifiably applies to later versions, please reopen with details and update the version.