Plugin Directory

Changeset 3208188


Ignore:
Timestamp:
12/15/2024 01:30:35 PM (14 months ago)
Author:
shinephp
Message:
  • Security Fix: Users - "Add Role", "Revoke Role" buttons: Cross-Site request forgery to privilege escalation was possible due to missed nonce validation. This issue was discovered and responsibly reported by vgo0.
Location:
user-role-editor/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • user-role-editor/trunk/changelog.txt

    r3201795 r3208188  
    11CHANGES LOG (full version).
    22===========================
     3
     4= [4.64.4] 15.12.2024 =
     5* Security Fix: Users - "Add Role", "Revoke Role" buttons: Cross-Site request forgery to privilege escalation was possible due to missed nonce validation. This issue was discovered and responsibly reported by vgo0.
    36
    47= [4.64.3] 03.12.2024 =
  • user-role-editor/trunk/includes/classes/ajax-processor.php

    r3037617 r3208188  
    4242   
    4343    protected function get_required_cap() {
    44        
    45         if ( $this->action=='grant_roles' || $this->action=='get_user_roles' ) {
     44        $promote_users_actions = array(
     45            'grant_roles',
     46            'get_user_roles',
     47            'add_role_to_user',
     48            'revoke_role_from_user'
     49        );
     50        if ( in_array( $this->action, $promote_users_actions ) ) {
    4651            $cap = 'promote_users';
    4752        } else {
     
    235240    }
    236241    // end of grant_roles()
    237    
     242
     243   
     244    protected function add_role_to_user() {
     245       
     246        $answer = URE_Grant_Roles::add_role();
     247       
     248        return $answer;
     249       
     250    }
     251    // end of add_role_to_user()
     252
     253   
     254    protected function revoke_role_from_user() {
     255       
     256        $answer = URE_Grant_Roles::revoke_role();
     257       
     258        return $answer;
     259       
     260    }
     261    // end of add_role_to_user()
    238262   
    239263    protected function get_user_roles() {
     
    330354                $answer = $this->grant_roles();
    331355                break;
     356            case 'add_role_to_user':
     357                $answer = $this->add_role_to_user();
     358                break;
     359            case 'revoke_role_from_user':
     360                $answer = $this->revoke_role_from_user();
     361                break;
    332362            case 'get_user_roles':
    333363                $answer = $this->get_user_roles();
  • user-role-editor/trunk/includes/classes/grant-roles.php

    r3201795 r3208188  
    2121    public function __construct() {
    2222       
    23         $this->lib = URE_Lib::get_instance();       
     23        $this->lib = URE_Lib::get_instance();
    2424       
    2525        add_action( 'load-users.php', array( $this, 'load' ) );               
     
    3333        add_action('restrict_manage_users', array($this, 'show_roles_manage_html') );
    3434        add_action('admin_head', array(User_Role_Editor::get_instance(), 'add_css_to_users_page') );
    35         add_action('admin_enqueue_scripts', array($this, 'load_js') );
    36        
    37         $this->update_roles(); 
     35        add_action('admin_enqueue_scripts', array($this, 'load_js') );       
    3836       
    3937    }
     
    6664   
    6765   
    68     private function add_role( $users ) {
    69        
    70         if ( !empty( $_REQUEST['ure_add_role'] ) ) {
    71             $role = $_REQUEST['ure_add_role'];
    72         } else {
    73             $role = $_REQUEST['ure_add_role_2'];
    74         }
    75 
     66    public static function add_role() {
     67       
     68        if ( !current_user_can('promote_users') ) {           
     69             $answer = array('result'=>'error', 'message'=>esc_html__('Not enough permissions', 'user-role-editor') );
     70             return $answer;
     71        }
     72       
     73        if ( empty( $_REQUEST['users'] ) ) {
     74            $answer = array('result'=>'error', 'message'=>esc_html__('Empty users list', 'user-role-editor') );
     75            return $answer;
     76        }                       
     77        $users = (array) $_REQUEST['users'];
     78        if ( !self::validate_users( $users ) ) {
     79            $answer = array('result'=>'error', 'message'=>esc_html__('Can not edit user or invalid data at the users list', 'user-role-editor') );
     80            return $answer;
     81        }
     82       
     83        $lib = URE_Lib::get_instance();
     84        $role = $lib->get_request_var('role', 'post', 'string');
    7685        if ( !self::validate_roles( array($role=>$role) ) ) {
    77             return;
    78         }
    79        
    80         $done = false;
     86            $answer = array('result'=>'error', 'message'=>esc_html__('Invalid role', 'user-role-editor') );
     87            return $answer;
     88        }
     89       
     90        $quantity = 0;
    8191        foreach( $users as $user_id ) {
    8292            $user = get_user_by( 'id', $user_id );
     
    8494                continue;
    8595            }
    86             if ( empty($user->roles) || !in_array( $role, $user->roles ) ) {
     96            if ( empty( $user->roles ) || !in_array( $role, $user->roles ) ) {
    8797                $user->add_role( $role );
    88                 $done = true;
    89             }
    90         }
    91        
    92         if ( $done ) {
    93             // Redirect to the users screen.
    94             if ( wp_redirect( add_query_arg( 'update', 'promote', 'users.php' ) ) ) {
    95                  exit;
    96             }
    97         }
     98                $quantity++;
     99            }
     100        }
     101       
     102        if ( $quantity>0 ) {
     103            // translators: template %d is a quantity of users to whom role was added
     104            $message = sprintf( esc_html__('Role added to %d user(s).', 'user-role-editor'), $quantity );
     105            $answer = array('result'=>'success', 'message'=>$message );
     106        } else {
     107            $answer = array('result'=>'error', 'message'=>esc_html__('Error: Role not added', 'user-role-editor') );
     108        }
     109       
     110        return $answer;
    98111    }
    99112    // end of add_role()
    100113   
    101114   
    102     private function is_try_remove_admin_from_himself( $user_id, $role) {
     115    private static function is_try_remove_admin_from_himself( $user_id, $role) {
    103116
    104117        $result = false;
     
    129142        return $result;
    130143    }
    131    
    132    
    133     private function revoke_role( $users ) {
    134        
    135         if ( !empty( $_REQUEST['ure_revoke_role'] ) ) {
    136             $role = $_REQUEST['ure_revoke_role'];
    137         } else {
    138             $role = $_REQUEST['ure_revoke_role_2'];
    139         }
    140 
     144    // end of is_try_remove_admin_from_himself()
     145   
     146   
     147    public static function revoke_role() {
     148       
     149        if ( !current_user_can('promote_users') ) {           
     150             $answer = array('result'=>'error', 'message'=>esc_html__('Not enough permissions', 'user-role-editor') );
     151             return $answer;
     152        }
     153       
     154        if ( empty( $_REQUEST['users'] ) ) {
     155            $answer = array('result'=>'error', 'message'=>esc_html__('Empty users list', 'user-role-editor') );
     156            return $answer;
     157        }                       
     158        $users = (array) $_REQUEST['users'];
     159        if ( !self::validate_users( $users ) ) {
     160            $answer = array('result'=>'error', 'message'=>esc_html__('Can not edit user or invalid data at the users list', 'user-role-editor') );
     161            return $answer;
     162        }
     163       
     164        $lib = URE_Lib::get_instance();
     165        $role = $lib->get_request_var('role', 'post', 'string');
    141166        if ( !self::validate_roles( array($role=>$role) ) ) {
    142             return;
    143         }
    144          
    145         $done = false;
     167            $answer = array('result'=>'error', 'message'=>esc_html__('Invalid role', 'user-role-editor') );
     168            return $answer;
     169        }
     170                 
     171        $quantity = 0;
    146172        foreach( $users as $user_id ) {
    147173            $user = get_user_by( 'id', $user_id );
    148             if (empty( $user ) ) {
     174            if ( empty( $user ) ) {
    149175                continue;
    150176            }
    151             if ($this->is_try_remove_admin_from_himself( $user_id, $role ) ) {
     177            if ( self::is_try_remove_admin_from_himself( $user_id, $role ) ) {
    152178                continue;
    153179            }
    154180            if ( is_array($user->roles) && in_array( $role, $user->roles ) ) {
    155181                $user->remove_role( $role );
    156                 $done = true;
    157             }
    158         }
    159         if ( $done ) {
    160             if ( wp_redirect( add_query_arg( 'update', 'promote', 'users.php' ) ) ) {
    161                 exit;
    162             }
    163         }
     182                $quantity++;
     183            }
     184        }
     185       
     186        if ( $quantity>0 ) {
     187            // translators: template %d is a quantity of users to whom role was added
     188            $message = sprintf( esc_html__('Role revoked from %d user(s).', 'user-role-editor'), $quantity );
     189            $answer = array('result'=>'success', 'message'=>$message );
     190        } else {
     191            $answer = array('result'=>'error', 'message'=>esc_html__('Error: Role not revoked', 'user-role-editor') );
     192        }       
     193       
     194        return $answer;
    164195    }
    165196    // end of revoke_role()
     
    191222   
    192223   
    193     private static function validate_roles($roles) {
    194 
    195         if (!is_array($roles)) {
     224    private static function validate_roles( $roles ) {
     225
     226        if ( !is_array( $roles ) ) {
    196227            return false;
    197228        }
     
    199230        $lib = URE_Lib::get_instance();
    200231        $editable_roles = $lib->get_all_editable_roles();
    201         $valid_roles = array_keys($editable_roles);
    202         foreach($roles as $role) {
    203             if (!in_array($role, $valid_roles)) {
     232        $valid_roles = array_keys( $editable_roles );
     233        foreach( $roles as $role ) {
     234            if ( !in_array( $role, $valid_roles ) ) {
    204235                return false;
    205236            }
     
    299330               
    300331        $users = $_POST['users'];       
    301         if (!self::validate_users($users)) {
    302             $answer = array('result'=>'error', 'message'=>esc_html__('Can not edit user or invalid data at the users list', 'user-role-editor'));
     332        if ( !self::validate_users( $users ) ) {
     333            $answer = array('result'=>'error', 'message'=>esc_html__('Can not edit user or invalid data at the users list', 'user-role-editor') );
    303334            return $answer;
    304335        }
     
    441472?>       
    442473          
    443         <input type="button" name="ure_grant_roles<?php echo $button_number;?>" id="ure_grant_roles<?php echo $button_number;?>" class="button"                               
     474        <input type="button" name="ure_grant_roles<?php echo $button_number;?>" id="ure_grant_roles<?php echo $button_number;?>" class="button"
    444475             value="<?php esc_html_e('Grant Roles', 'user-role-editor');?>">
    445         &nbsp;&nbsp;       
     476        &nbsp;&nbsp;
    446477        <label class="screen-reader-text" for="ure_add_role<?php echo $button_number;?>"><?php esc_html_e( 'Add role&hellip;', 'user-role-editor' ); ?></label>
    447478        <select name="ure_add_role<?php echo $button_number;?>" id="ure_add_role<?php echo $button_number;?>" style="display: inline-block; float: none;">
     
    449480            <?php echo $roles_options_list; ?>
    450481        </select>
    451     <?php submit_button( esc_html__( 'Add', 'user-role-editor' ), 'secondary', 'ure_add_role_submit'.$button_number, false ); ?>
     482        <input type="button" name="ure_add_role_button<?php echo $button_number;?>" id="ure_add_role_button<?php echo $button_number;?>" class="button"
     483             value="<?php esc_html_e('Add', 'user-role-editor');?>">
    452484        &nbsp;&nbsp;
    453485        <label class="screen-reader-text" for="ure_revoke_role<?php echo $button_number;?>"><?php esc_html_e( 'Revoke role&hellip;', 'user-role-editor' ); ?></label>
     
    456488            <?php echo $roles_options_list; ?>
    457489        </select>
    458     <?php submit_button( esc_html__( 'Revoke', 'user-role-editor' ), 'secondary', 'ure_revoke_role_submit'.$button_number, false ); ?>
     490    <input type="button" name="ure_revoke_role_button<?php echo $button_number;?>" id="ure_revoke_role_button<?php echo $button_number;?>" class="button"
     491             value="<?php esc_html_e('Revoke', 'user-role-editor');?>">
    459492
    460493       
     
    491524            'select_users_first' => esc_html__('Select users to which you wish to grant roles!', 'user-role-editor'),
    492525            'select_roles_first' => esc_html__('Select role(s) which you wish to grant!', 'user-role-editor'),
     526            'select_role_first' => esc_html__('Select role first!', 'user-role-editor'),
     527            'select_users_to_add_role' => esc_html__('Select users to which you wish to add role!', 'user-role-editor'),
     528            'select_users_to_revoke_role' => esc_html__('Select users from which you wish revoke role!', 'user-role-editor'),
    493529            'show_wp_change_role' => $show_wp_change_role ? 1: 0
    494530        ));
  • user-role-editor/trunk/js/users-grant-roles.js

    r2715703 r3208188  
    1111        ure_prepare_grant_roles_dialog();
    1212    });
     13    jQuery('#ure_add_role_button').click(function() {
     14        ure_add_role( 1 );
     15    });
     16    jQuery('#ure_add_role_button_2').click(function() {
     17        ure_add_role( 2 );
     18    });
     19    jQuery('#ure_revoke_role_button').click(function() {
     20        ure_revoke_role( 1 );
     21    });
     22    jQuery('#ure_revoke_role_button_2').click(function() {
     23        ure_revoke_role( 2 );
     24    });
     25
    1326   
    1427    if (ure_users_grant_roles_data.show_wp_change_role!=1) {       
     
    124137        'primary_role': primary_role,
    125138        'other_roles': other_roles,
    126         'wp_nonce': ure_users_grant_roles_data.wp_nonce};
     139        'wp_nonce': ure_users_grant_roles_data.wp_nonce
     140    };
     141    jQuery.post(ajaxurl, data, ure_page_reload, 'json');
     142   
     143    return true;
     144}
     145
     146
     147function ure_add_role( control_number ) {   
     148    var users = ure_get_selected_checkboxes('users');
     149    if ( users.length===0 ) {
     150        alert( ure_users_grant_roles_data.select_users_to_add_role );
     151        return;
     152    }
     153   
     154    var modifier = ( control_number===2 ) ? '_2' : '';
     155    var role = jQuery('#ure_add_role'+ modifier).val();
     156    if ( role.length===0 ) {
     157         alert( ure_users_grant_roles_data.select_role_first );
     158         return;
     159    }
     160   
     161    jQuery('#ure_task_status').show();   
     162    var data = {
     163        'action': 'ure_ajax',
     164        'sub_action':'add_role_to_user',
     165        'users': users,
     166        'role': role,
     167        'wp_nonce': ure_users_grant_roles_data.wp_nonce
     168    };
     169    jQuery.post(ajaxurl, data, ure_page_reload, 'json');
     170   
     171    return true;
     172}
     173
     174
     175function ure_revoke_role( control_number ) {   
     176    var users = ure_get_selected_checkboxes('users');
     177    if ( users.length===0 ) {
     178        alert( ure_users_grant_roles_data.select_users_to_revoke_role );
     179        return;
     180    }
     181   
     182    var modifier = ( control_number===2 ) ? '_2' : '';
     183    var role = jQuery('#ure_revoke_role'+ modifier).val();
     184    if ( role.length===0 ) {
     185         alert( ure_users_grant_roles_data.select_role_first );
     186         return;
     187    }
     188   
     189    jQuery('#ure_task_status').show();   
     190    var data = {
     191        'action': 'ure_ajax',
     192        'sub_action':'revoke_role_from_user',
     193        'users': users,
     194        'role': role,
     195        'wp_nonce': ure_users_grant_roles_data.wp_nonce
     196    };
    127197    jQuery.post(ajaxurl, data, ure_page_reload, 'json');
    128198   
     
    164234    var url = ure_set_url_arg('update', 'promote');
    165235    document.location = url;
    166 }
     236   
     237}
  • user-role-editor/trunk/readme.txt

    r3202014 r3208188  
    8282
    8383== Changelog =
     84= [4.64.4] 15.12.2024 =
     85* Security Fix: Users - "Add Role", "Revoke Role" buttons: Cross-Site request forgery to privilege escalation was possible due to missed nonce validation. This issue was discovered and responsibly reported by vgo0.
    8486
    8587= [4.64.3] 03.12.2024 =
     
    8789* Fix: PHP Notice:  "Function _load_textdomain_just_in_time was called incorrectly. Translation loading for the <code>user-role-editor</code> domain was triggered too early." was fixed (shown only for those who used own .mo translation file installed).
    8890* Fix: Miscellaneous translation functionality (l18n) usage enhancements were applied.
    89 
    90 = [4.64.2] 19.02.2024 =
    91 * Update: Marked as compatible with WordPress 6.4.3
    92 * Update: URE_Advertisement: rand() is replaced with wp_rand().
    93 * Update: URE_Ajax_Proccessor: json_encode() is replaced with wp_json_encode().
    94 * Update: User_Role_Editor::load_translation(): load_plugin_textdomain() is called with the 2nd parameter value false, instead of deprecated ''.
    95 * Update: URE_Lib::is_right_admin_path(): parse_url() is replaced with wp_parse_url().
    96 * Update: URE_Lib::user_is_admin() does not call WP_User::has_cap() to enhance performance.
    97 * Update: Plugin version was added to CSS loaded to the "Users", "Users->User Role Editor", "Settings->User Role Editor" pages.
    98 * Update: All JavaScript files are loaded in footer now.
    99 * Fix: "Users->Add New Users". Unneeded extra '<table></table>' HTML tags was removed (thanks to Alejandro A. for this bug report).
    100 
    101 = [4.64.1] 24.10.2023 =
    102 * Update: Marked as compatible with WordPress 6.4
    103 * Fix: Notice shown by PHP 8.3 is removed: PHP Deprecated: Creation of dynamic property URE_Editor::$hide_pro_banner is deprecated in /wp-content/plugins/user-role-editor/includes/classes/editor.php on line 166
    104 * Fix: Notice shown by PHP 8.3 is removed: PHP Deprecated: Creation of dynamic property URE_Role_View::$caps_to_remove is deprecated in /wp-content/plugins/user-role-editor/includes/classes/role-view.php on line 23
    105 * Fix: Notice shown by PHP 8.3 is removed: PHP Deprecated: Function utf8_decode() is deprecated in /wp-content/plugins/user-role-editor-pro/includes/classes/editor.php on line 984
    106 
    10791
    10892File changelog.txt contains the full list of changes.
     
    116100== Upgrade Notice ==
    117101
    118 = [4.64.2] 19.02.2023 =
    119 * Update: URE_Advertisement: rand() is replaced with wp_rand().
    120 * Update: URE_Ajax_Proccessor: json_encode() is replaced with wp_json_encode().
    121 * Update: User_Role_Editor::load_translation(): load_plugin_textdomain() is called with the 2nd parameter value false, instead of deprecated ''.
    122 * Update: URE_Lib::is_right_admin_path(): parse_url() is replaced with wp_parse_url().
    123 * Update: URE_Lib::user_is_admin() does not call WP_User::has_cap() to enhance performance.
    124 * Update: Plugin version was added to CSS loaded to the "Users", "Users->User Role Editor", "Settings->User Role Editor" pages.
    125 * Update: All JavaScript files are loaded in footer now.
    126 * Fix: "Users->Add New Users". Unneeded extra '<table></table>' HTML tags was removed (thanks to Alejandro A. for this bug report).
     102= [4.64.4] 15.12.2024 =
     103* Security Fix: Users - "Add Role", "Revoke Role" buttons: Cross-Site request forgery to privilege escalation was possible due to missed nonce validation. This issue was discovered and responsibly reported by vgo0.
Note: See TracChangeset for help on using the changeset viewer.