Cross-Site Request Forgery (CSRF) Vulnerability in wpDiscuz
As we continue looking at ways we can improve the security of WordPress plugins, one of the thing we are trying is checking over plugins that we have recently added new vulnerabilities to our data set to see if we can find any other obvious vulnerabilities. The first vulnerability we have discovered is a really minor vulnerability, that would be more of an annoyance than a serious threat. In version 3.2.8 of the plugin wpDiscuz we found that there is no protection against cross-site request forgery (CSRF) when resetting the plugins settings. So if you can trick an Administrator level user in to visiting the URL that causes that, the reset will occur without them intending it. It seems to be a simple oversight as the two buttons next to it on the settings page do have the proper protection.
The reset is handle in the file /options/html-options.php at:
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | if (isset($_GET['wpdiscuz_reset_options']) && $_GET['wpdiscuz_reset_options'] == 1 && current_user_can('manage_options')) { delete_option(WpdiscuzCore::OPTION_SLUG_OPTIONS); $this->optionsSerialized->postTypes = array('post'); $this->optionsSerialized->shareButtons = array('fb', 'twitter', 'google'); $this->optionsSerialized->addOptions(); $this->optionsSerialized->initOptions(get_option(WpdiscuzCore::OPTION_SLUG_OPTIONS)); $this->optionsSerialized->blogRoles['post_author'] = '#00B38F'; $blogRoles = get_editable_roles(); foreach ($blogRoles as $roleName => $roleInfo) { $this->optionsSerialized->blogRoles[$roleName] = '#00B38F'; } $this->optionsSerialized->blogRoles['guest'] = '#00B38F'; $this->optionsSerialized->showPluginPoweredByLink = 1; $this->optionsSerialized->updateOptions(); do_action('wpdiscuz_reset_options'); } |
You can see that a capabilities check is done, so lower level users can’t cause a reset, but there is no nonce check done.
Proof of Concept
When logged in as an Administrator visiting the following URL will reset all the plugin’s settings.
Make sure to replace “[path to WordPress]” with the location of WordPress.
http://[path to WordPress]/wp-admin/edit-comments.php?page=wpdiscuz_options_page&wpdiscuz_reset_options=1
Timeline
- 6/13/2016 – Developer notified.
- 11/5/2016 – Version 4.0.0 released, which fixes issue.