WordPress Kali Forms plugin fixed multiple vulnerabilities.

The WordPress Kali Forms plugin (30,000+ active installations) fixed multiple vulnerabilities. Affected versions are 2.1.0 and below and, to some extend, version 2.1.1 (see Timeline below for more details).

Unauthenticated Arbitrary Post Deletion

In the “kali-forms/Inc/Frontend/class-form-processor.php” script L91-92, the plugin registers the kaliforms_form_delete_uploaded_file AJAX action to call the “delete_file” function, and makes it accessible to all users, authenticated or not:

add_action('wp_ajax_kaliforms_form_delete_uploaded_file', [$this, 'delete_file']);
add_action('wp_ajax_nopriv_kaliforms_form_delete_uploaded_file', [$this, 'delete_file']);

The function is located in the “kali-forms/Inc/Utils/class-filemanager.php” L138:

public function delete_file()
{
   $_POST['id'] = absint(wp_unslash($_POST['id']));
   return wp_delete_post($_POST['id'], true);
}

It takes the value of $_POST['id'] and calls the wp_delete_post function.
An unauthenticated user can delete every page and post on the blog.

Authenticated Options Change

In the “/kali-forms/Inc/Backend/class-hooks.php” script L63, the plugin registers the kaliforms_update_option_ajax AJAX action to call the “update_option” function and makes it accessible to authenticated users:

add_action('wp_ajax_kaliforms_update_option_ajax',
   [$this, 'update_option']
);

The “update_option” function is located in the same script L125:

public function update_option()
{
   if (isset($_POST['args'], $_POST['args']['nonce'])
      && !wp_verify_nonce(sanitize_key(wp_unslash($_POST['args']['nonce'])), $this->slug . '_nonce')) {
   	wp_die(wp_json_encode([
   	   'success' => false,
   	   'message' => esc_html__('Denied', 'kaliforms'),
   	]));
   }
   	
   $args = stripslashes_deep($_POST['args']);
   $args['method'] === 'delete'
   ? delete_option($this->slug . '_' . $args['option']['key'])
   : update_option($this->slug . '_' . $args['option']['key'], sanitize_text_field($args['option']['value']));
   	
   wp_die(wp_json_encode([
      'success' => true,
      'message' => 'ok - updated option: ' . $args['option']['key'] . ' with the value: ' . $args['option']['value'],
   ]));
}

It lacks a capability check and the security nonce can be bypassed because the $_POST['args']['nonce'] input is only checked if it is set.
An authenticated user can change (or delete) the plugin’s settings. For instance, by modifying the SMTP server credentials settings (e.g., kaliforms_smtp_provider, kaliforms_smtp_host, kaliforms_smtp_username, kaliforms_smtp_password etc), all submitted form data will be redirected to the attacker’s mailbox/SMTP server.

CSRF

Throughout the plugin’s code, security nonces can be bypassed because they are only checked if they are set:
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Utils/class-duplicate-post.php#L49
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Frontend/class-form-processor.php#L242
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Frontend/class-form-processor.php#L655
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Backend/class-form-styles.php#L75
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Backend/class-plugin-health-checks.php#L216
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Backend/class-plugin-review.php#L156
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Backend/class-hooks.php#L152
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Backend/class-predefined-forms.php#L44
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Backend/class-plugin-deactivation.php#L96
-https://plugins.trac.wordpress.org/browser/kali-forms/tags/2.1.0/Inc/Backend/class-notifications.php#L107

Additional Issues

In the “kali-forms/Inc/Backend/class-hooks.php”, the “clear_mail_log” function L150 is loaded by the kaliforms_clear_log AJAX action L66. There’s no capability check, any authenticated user can delete the plugin’s log.

Timeline

The vulnerabilities were reported to the wordpress.org plugins team on August 7th, 2020 and a new version 2.1.1 was released on August 15th. However, because that version introduced two new vulnerabilities, version 2.1.2 was released on August 17th, 2020.

Recommendations

Upgrade immediately if you have version 2.1.1 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 vulnerability.

Stay informed about the latest vulnerabilities