update plugins
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Main class of User Role Editor WordPress plugin
|
||||
* Author: Vladimir Garagulya
|
||||
* Author email: support@role-editor.com
|
||||
* Author URI: https://www.role-editor.com
|
||||
* License: GPL v2+
|
||||
*
|
||||
*/
|
||||
|
||||
class URE_Protect_Admin {
|
||||
|
||||
private $lib = null;
|
||||
private $user_to_check = null; // cached list of user IDs, who has Administrator role
|
||||
|
||||
public function __construct() {
|
||||
global $pagenow;
|
||||
|
||||
$this->lib = URE_Lib::get_instance();
|
||||
$this->user_to_check = array();
|
||||
|
||||
// Exclude administrator role from edit list.
|
||||
add_filter('editable_roles', array($this, 'exclude_admin_role'));
|
||||
if (in_array($pagenow, array('users.php', 'user-edit.php'))) {
|
||||
// prohibit any actions with user who has Administrator role
|
||||
add_filter('user_has_cap', array($this, 'not_edit_admin'), 10, 3);
|
||||
}
|
||||
// exclude users with 'Administrator' role from users list
|
||||
add_action('pre_user_query', array($this, 'exclude_administrators'));
|
||||
// do not show 'Administrator (s)' view above users list
|
||||
add_filter('views_users', array($this, 'exclude_admins_view'));
|
||||
}
|
||||
// end of __construct()
|
||||
|
||||
|
||||
// apply protection to the user edit pages only
|
||||
protected function is_protection_applicable() {
|
||||
global $pagenow;
|
||||
|
||||
$result = false;
|
||||
$pages_to_block = array('profile.php', 'users.php', 'user-new.php', 'user-edit.php');
|
||||
if (in_array($pagenow, $pages_to_block)) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
// end of is_protection_applicable()
|
||||
|
||||
|
||||
/**
|
||||
* exclude administrator role from the roles list
|
||||
*
|
||||
* @param string $roles
|
||||
* @return array
|
||||
*/
|
||||
public function exclude_admin_role( $roles ) {
|
||||
|
||||
if ( $this->is_protection_applicable() && isset( $roles['administrator'] ) ) {
|
||||
unset( $roles['administrator'] );
|
||||
}
|
||||
|
||||
return $roles;
|
||||
}
|
||||
// end of exclude_admin_role()
|
||||
|
||||
|
||||
/**
|
||||
* Check if user has "Administrator" role assigned
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
* @param int $user_id
|
||||
* @return boolean returns true is user has Role "Administrator"
|
||||
*/
|
||||
private function has_administrator_role($user_id) {
|
||||
global $wpdb;
|
||||
|
||||
if (empty($user_id) || !is_numeric($user_id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$meta_key = $wpdb->prefix .'capabilities';
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT count(*)
|
||||
FROM {$wpdb->usermeta}
|
||||
WHERE user_id=%d AND meta_key=%s AND meta_value LIKE %s",
|
||||
array($user_id, $meta_key, '%"administrator"%') );
|
||||
$has_admin_role = $wpdb->get_var( $query );
|
||||
if ($has_admin_role > 0) {
|
||||
$result = true;
|
||||
} else {
|
||||
$result = false;
|
||||
}
|
||||
// cache checking result for the future use
|
||||
$this->user_to_check[$user_id] = $result;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// end of has_administrator_role()
|
||||
|
||||
|
||||
/**
|
||||
* We have two vulnerable queries with user id at admin interface, which should be processed
|
||||
* 1st: http://blogdomain.com/wp-admin/user-edit.php?user_id=ID&wp_http_referer=%2Fwp-admin%2Fusers.php
|
||||
* 2nd: http://blogdomain.com/wp-admin/users.php?action=delete&user=ID&_wpnonce=ab34225a78
|
||||
* If put Administrator user ID into such request, user with lower capabilities (if he has 'edit_users')
|
||||
* can edit, delete admin record
|
||||
* This function removes 'edit_users' or 'delete_users' or 'remove_users' capability from current user capabilities,
|
||||
* if request sent against a user with 'administrator' role
|
||||
*
|
||||
* @param array $allcaps
|
||||
* @param type $caps
|
||||
* @param string $name
|
||||
* @return array
|
||||
*/
|
||||
public function not_edit_admin($allcaps, $caps, $name) {
|
||||
|
||||
if (is_array($caps) & count($caps)>0) {
|
||||
// 1st element of this array not always has index 0. Use workaround to extract it.
|
||||
$caps_v = array_values($caps);
|
||||
$cap = $caps_v[0];
|
||||
} else {
|
||||
$cap = $caps;
|
||||
}
|
||||
$checked_caps = array('edit_users', 'delete_users', 'remove_users');
|
||||
if (!in_array($cap, $checked_caps)) {
|
||||
return $allcaps;
|
||||
}
|
||||
|
||||
$user_keys = array('user_id', 'user');
|
||||
foreach ($user_keys as $user_key) {
|
||||
$access_deny = false;
|
||||
$user_id = (int) $this->lib->get_request_var($user_key, 'get', 'int');
|
||||
if (empty($user_id)) { // check the next key
|
||||
continue;
|
||||
}
|
||||
if ($user_id == 1) { // built-in WordPress Admin
|
||||
$access_deny = true;
|
||||
} else {
|
||||
if (!isset($this->user_to_check[$user_id])) {
|
||||
// check if user_id has Administrator role
|
||||
$access_deny = $this->has_administrator_role($user_id);
|
||||
} else {
|
||||
// user_id was checked already, get result from cash
|
||||
$access_deny = $this->user_to_check[$user_id];
|
||||
}
|
||||
}
|
||||
if ($access_deny && isset($allcaps[$cap])) {
|
||||
unset($allcaps[$cap]);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $allcaps;
|
||||
}
|
||||
// end of not_edit_admin()
|
||||
|
||||
|
||||
/**
|
||||
* add where criteria to exclude users with 'Administrator' role from users list
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
* @param type $user_query
|
||||
*/
|
||||
public function exclude_administrators($user_query) {
|
||||
global $wpdb;
|
||||
|
||||
if (!$this->is_protection_applicable()) { // block the user edit stuff only
|
||||
return;
|
||||
}
|
||||
|
||||
// get user_id of users with 'Administrator' role
|
||||
$current_user_id = get_current_user_id();
|
||||
$meta_key = $wpdb->prefix . 'capabilities';
|
||||
$query = $wpdb->prepare(
|
||||
"SELECT user_id
|
||||
FROM {$wpdb->usermeta}
|
||||
WHERE user_id!=%d AND meta_key=%s AND meta_value like %s",
|
||||
array($current_user_id, $meta_key, '%"administrator"%'));
|
||||
$ids_arr = $wpdb->get_col( $query );
|
||||
if (is_array($ids_arr) && count($ids_arr) > 0) {
|
||||
$ids = implode(',', $ids_arr);
|
||||
$user_query->query_where .= " AND ( $wpdb->users.ID NOT IN ( $ids ) )";
|
||||
}
|
||||
}
|
||||
// end of exclude_administrators()
|
||||
|
||||
|
||||
private function extract_view_quantity($text) {
|
||||
$match = array();
|
||||
$result = preg_match('#\((.*?)\)#', $text, $match);
|
||||
if ($result) {
|
||||
$quantity = $match[1];
|
||||
} else {
|
||||
$quantity = 0;
|
||||
}
|
||||
|
||||
return $quantity;
|
||||
}
|
||||
// end of extract_view_quantity()
|
||||
|
||||
|
||||
private function extract_int($str_val) {
|
||||
$str_val1 = str_replace(',', '', $str_val); // remove ',' from numbers like '2,015'
|
||||
$int_val = (int) preg_replace('/[^\-\d]*(\-?\d*).*/','$1', $str_val1); // extract numeric value strings like from '2015 bla-bla'
|
||||
|
||||
return $int_val;
|
||||
}
|
||||
// end of extract_int()
|
||||
|
||||
|
||||
/*
|
||||
* Exclude view of users with Administrator role
|
||||
*
|
||||
*/
|
||||
public function exclude_admins_view($views) {
|
||||
|
||||
if (!isset($views['administrator'])) {
|
||||
return $views;
|
||||
}
|
||||
|
||||
if (isset($views['all'])) {
|
||||
// Decrease quant of all users for a quant of hidden admins
|
||||
$admins_orig_s = $this->extract_view_quantity($views['administrator']);
|
||||
$admins_int = $this->extract_int($admins_orig_s);
|
||||
$all_orig_s = $this->extract_view_quantity($views['all']);
|
||||
$all_orig_int = $this->extract_int($all_orig_s);
|
||||
$all_new_int = $all_orig_int - $admins_int;
|
||||
$all_new_s = number_format_i18n($all_new_int);
|
||||
$views['all'] = str_replace($all_orig_s, $all_new_s, $views['all']);
|
||||
}
|
||||
|
||||
unset($views['administrator']);
|
||||
|
||||
return $views;
|
||||
}
|
||||
// end of exclude_admins_view()
|
||||
|
||||
}
|
||||
// end of URE_Protect_Admin class
|
||||
Reference in New Issue
Block a user