[wp-trac] [WordPress Trac] #8770: Add role filtering to user
editing code to secure edit_users capabiltity (security)
WordPress Trac
wp-trac at lists.automattic.com
Wed Dec 31 21:37:06 GMT 2008
#8770: Add role filtering to user editing code to secure edit_users capabiltity
(security)
--------------------------+-------------------------------------------------
Reporter: jeremyclarke | Owner: jeremyclarke
Type: defect (bug) | Status: new
Priority: normal | Milestone: 2.8
Component: Security | Version:
Severity: normal | Keywords: has-patch capabilities needs-testing
--------------------------+-------------------------------------------------
For history see: #6014
I'm updating that patch so it can be added to 2.8, but i'm splitting up
the various parts so they can be added more easily.
Part 1 was #8760 (fix display of checkboxes on user listing), now
commited. Part 2 was #8761 (add filter to wp_dropdown_roles), now
committed. #8764 is another important patch that changes the user editing
page (user-edit.php) to use the wp_dropdown_roles() function instead of
duplicating its effect.
What I want (same as #8760): To add security to the capabilities system
because right now edit_users can't be delegated to non-admins (in our case
our content editors). If someone has 'edit_users' they can make themself
admin because nothing stops them from editing themselves or others to be
admin. I think it should be integrated into core but don't care enough to
fight. It can be done with a plugin so my priority is to make sure that my
plugin (and Role Manager plugin) can hook into the appropriate places and
add a role comparison such that wp only lets people edit users/roles
"lower" than them (i.e. users that don't have any powers that the editor
don't have).
This is hopefully the final ticket to make the system safe and secure (or
make it so a plugin can secure the system).
In the patch to wp-admin/includes/user.php I make several changes
* add a new function get_editable_roles() : This matches similar
functions like get_editable_user_ids() and serves to centralize the use of
the new filter 'editable_roles'. This function should be used any time a
role is going to be or is about to be changed. I use it in the updated
wp_dropdown_roles() to filter the list of roles before printing them out
as <option> elements. It also needs to be used in functions like
edit_user(), where it returns a list of roles that the logged-in user is
allowed to edit, thus giving an opportunity to stop the edit if the new
role is innapropriate (i.e. stop an 'author' or someone similar from
crafting a malicious $_POST request to get around the limitation)
* add the new function and a check to edit_user() and add_user() so that
those functions die if the roles are innapropriate
* fixed, added etc phpdoc for functions i worked on.
In the patch to wp-admin/includes/template.php:
* I edit the wp_dropdown_roles() function to use the new
get_editable_roles() function (instead of running the filter manually), as
well as changing the format a bit to use the $wp_roles->roles array
instead of the $wp_roles->role_names one (i figure we might as well pass
in the more detailed version for the filter, as the effect is the same
anyway and the filter didn't exist before).
* Note: When my first changes to wp_dropdown_roles were committed it used
a filter called "role_names_listing". This has been completely replaced
with the more generic filter "editable_roles", which is used in
get_editable_roles. No mention of the old label should exist. This is just
mentioned here in case someone gets confused about the previous patch. I'm
sure no one will start using the old filter between these two patches
(we're in very early 2.8 right now).
Finally, my patch for /wp-admin/users.php (the user listing page) :
* I added a call to get_editable_roles and a check against them in the
section that handles bulk user role changes (i.e. using checkboxes and the
pulldowns). This should be useful to stop any malicious $_POST requests
that try to get around the already limited pulldown.
* I also removed a redundant check to "if (
!current_user_can('edit_users') )" because a few lines later we do a more
specific check to "current_user_can('edit_user', $id)", which will kill
the process anyway if hte logged-in user can't 'edit_users'.
So these three patches need to be integrated as well as the one in #8764,
then I will leave you alone :)
Feedback welcome.
--
Ticket URL: <http://trac.wordpress.org/ticket/8770>
WordPress Trac <http://trac.wordpress.org/>
WordPress blogging software
More information about the wp-trac
mailing list