Privilege escalation vulnerability in WordPress ND Restaurant Reservations plugin.

The WordPress ND Restaurant Reservations plugin, which has 300+ active installations, was prone to a critical vulnerability that would allow an unauthenticated user to modify the settings of WordPress and to take over the blog and its database.

Note that this vulnerability is similar to the ND Shortcodes For Visual Composer plugin vulnerability, except that it does not require the blog to be using one of the author’s themes, i.e., all active installations are vulnerable.

Unauthenticated options change

In version <=1.3, the plugin registers the nd_rst_import_settings_php_function action via both the wp_ajax_* and wp_ajax_nopriv_* hooks in the ‘nd-restaurant-reservations/inc/admin/7-import-export/index.php’ script:

add_action( 'wp_ajax_nd_rst_import_settings_php_function', 'nd_rst_import_settings_php_function' );
add_action( 'wp_ajax_nopriv_nd_rst_import_settings_php_function', 'nd_rst_import_settings_php_function' );

The wp_ajax_* hook allows logged-in users to access WordPress AJAX functions while the wp_ajax_nopriv_* hooks allows unauthenticated users to perform the same action. In ND Restaurant Reservations, the AJAX request is sent to the ‘nd_rst_import_settings_php_function’ function used to import the plugin settings:

function nd_rst_import_settings_php_function() {


  //recover datas
  $nd_rst_value_import_settings = $_GET['nd_rst_value_import_settings'];

  $nd_rst_import_settings_result = '';

  if ( $nd_rst_value_import_settings != '' ) {

    $nd_rst_array_options = explode("[nd_rst_end_option]", $nd_rst_value_import_settings);

    foreach ($nd_rst_array_options as $nd_rst_array_option) {
        
      $nd_rst_array_single_option = explode("[nd_rst_option_value]", $nd_rst_array_option);
      $nd_rst_option = $nd_rst_array_single_option[0];
      $nd_rst_new_value = $nd_rst_array_single_option[1];
      $nd_rst_new_value = str_replace("[SHARP]","#",$nd_rst_new_value);

      if ( $nd_rst_new_value != '' ){
        $nd_rst_update_result = update_option($nd_rst_option,$nd_rst_new_value);  
 

The $_GET['nd_rst_value_import_settings'] payload will be passed on, unverified, to the update_option function. Because there’s no capability check and the function is accessible to anyone, an unauthenticated user can change the blog settings, for instance the site URL, the admin email address, user roles and capabilities, or give administrator privilege to any new registered user.

Timeline

The vulnerability was discovered and reported to the wordpress.org team on July 24, 2019.

Recommendations

Update as soon as possible if you are using version 1.3 or below.
If you are using our web application firewall for WordPress, NinjaFirewall WP Edition (free) and NinjaFirewall WP+ Edition (premium), you are protected against this type of vulnerability.

Stay informed about the latest vulnerabilities in WordPress plugins and themes: @nintechnet