WPScan Misses Real Security Issue in WordPress Plugin with 600,000+ Installs Despite Claiming to Have Verified Related “Vulnerability”
On July 18 a new version of the WordPress plugin Maintenance was released, which appeared to have a security improvement in it based on one of the changelog entries:
security fixes
Our monitoring systems notified us of that and we went to check if there was a vulnerability being fixed that we should notify customers of our service that were using that plugin about.
What we found was that there wasn’t a vulnerability being fixed, but there still was a very obvious security issue in the code related to the change being made. It is something that you shouldn’t expect to see in a very popular plugin, but despite the plugin having 600,000+ installs according to wordpress.org, the issue exists.
Based on the change made, we assumed this involved one or more of the security companies that are the usual suspects out there spreading false reports of vulnerabilities. If that were the case, we were curious to see if any of them would notice the real security issue that was still in the plugin. Not surprisingly, one of the spread the false claim that there had been a vulnerability in the plugin, but they missed the real security issue, despite claiming to have verified the vulnerability. If they had actually verified the vulnerability, they couldn’t have missed that issue.
That usual suspect being WPScan. Here is how they described the “vulnerability” they claimed was in this:
The plugin does not sanitise or escape some of its settings, allowing high privilege users such as admin to se Cross-Site Scripting payload in them (even when the unfiltered_html capability is disallowed), which will be triggered in the frontend
Another way to put that, is that they are claiming there is a vulnerability that can only be exploited by Administrators. Administrators can do whatever they want (since they are Administrators), including removing security code from plugins, so it wouldn’t be a vulnerability to do what is mentioned in the report.
WPScan claims to have verified this report:
As we have noted, recently they are clearly not doing verification in at least some instances, because beyond something like this not being a vulnerability, they have managed to miss a real vulnerability that we caught when we did the due diligence on one of these reports.
Part of the due diligence you want to do with a report like this is to see what security checks are done before saving the settings.
With this plugin, the saving of the new values of the settings occurs in the function mtnc_register_settings(), which runs during admin_init:
9 | add_action('admin_init', 'mtnc_register_settings'); |
That normally means it can run even for someone not logged in to WordPress, so you want to do a capabilities check before saving the settings. In this situation things are more restricted, as that registration only occurs if admin_menu runs:
2 3 4 5 6 7 8 9 | add_action('admin_menu', 'mtnc_admin_setup'); function mtnc_admin_setup() { global $mtnc_variable; $mtnc_variable->options_page = add_menu_page(__('Maintenance', 'maintenance'), __('Maintenance', 'maintenance'), 'manage_options', 'maintenance', 'mtnc_manage_options', MTNC_URI . 'images/icon-small.png'); add_action('admin_init', 'mtnc_register_settings'); |
It looks like that restricts access to those logged in to WordPress that can access WordPress admin area, but that would still allow low privileged users access, so there still needs to be a capabilities check.
Here is the mtnc_register_settings() function:
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | function mtnc_register_settings() { if (!empty($_POST['lib_options']) && check_admin_referer('mtnc_edit_post', 'mtnc_nonce')) { if (!isset($_POST['lib_options']['state'])) { $_POST['lib_options']['state'] = 0; } else { $_POST['lib_options']['state'] = 1; } if (isset($_POST['lib_options']['htmlcss'])) { $_POST['lib_options']['htmlcss'] = wp_kses_stripslashes($_POST['lib_options']['htmlcss']); // Allowed all tags as for WYSIWYG post content } if (isset($_POST['lib_options'])) { $lib_options = sanitize_post(wp_unslash($_POST['lib_options']), 'db'); $lib_options['default_settings'] = false; update_option('maintenance_options', $lib_options); MTNC::mtnc_clear_cache(); } } } |
That capabilities check is missing. There is a nonce check that would normally provide the equivalent of that since a valid nonce would be needed and access to that is restricted, but the WordPress documentation specially warns against relying on that for that purpose:
Nonces should never be relied on for authentication, authorization, or access control. Protect your functions using current_user_can(), and always assume nonces can be compromised.
In the case of this plugin, that nonce is only included on the plugin’s settings page, which is restricted to users with the manage_options capability, so Administrators would have access to it:
7 | $mtnc_variable->options_page = add_menu_page(__('Maintenance', 'maintenance'), __('Maintenance', 'maintenance'), 'manage_options', 'maintenance', 'mtnc_manage_options', MTNC_URI . 'images/icon-small.png'); |
We have notified the developer of that security issue.
Why is Automattic Sponsoring This?
Summing this up, you have got a situation where WPScan is not telling the truth about a claimed vulnerability or verifying it, while managing to miss a real security issue here. It is quite a mess. For some reason, despite that, Automattic is sponsoring them: