Patchstack, Wordfence, and Developer Make Mess of Minor Vulnerability in 100,000+ Install WordPress Plugin
On Friday, the 100,000+ install WordPress plugin Optimize Database after Deleting Revisions was closed on the WordPress Plugin Directory without any explanation. The lack of explanation isn’t helpful for users of the plugin. A likely explanation of this is a mess related to a minor security vulnerability in the plugin. That vulnerability has been poorly handled by the Patchstack, which started things, as well as Wordfence and the developer of the plugin.
Users of the plugin have been left without clear information on what is going on with the vulnerability claim for months, which hopefully can clear up.
In late July, Patchstack vaguely claimed the plugin contained a cross-site request forgery (CSRF) vulnerability. Here are the current “details” they give:
Mika discovered and reported this Cross Site Request Forgery (CSRF) vulnerability in WordPress Optimize Database after Deleting Revisions Plugin. This could allow a malicious actor to force higher privileged users to execute unwanted actions under their current authentication. This vulnerability has not been known to be fixed yet.
Those are not really details and it is impossible to know what they were referring to. This is a common issue with them and leads to a lot of problems.
Days later, the developer replied to a support forum topic asking how to address this. We emailed them explaining the details of two issues, which we will get in to later in the post, that could be what Patchstack was referencing. We also pointed to the WordPress documentation on how to address the issues and offered to help the developer to address them. We never got any response.
The developer subsequently addressed one of the issues and said things were resolved.
At that point things get confusing, as Patchstack still said there was an issue, but Wordfence said it was fixed. Looking back at this now, we were confused as well, because our own communication with the developer mentioned Wordfence claiming something that didn’t match up with what Wordfence is now saying. It turned out that was because Wordfence completely changed what they claimed was the vulnerability.
Here was Wordfence’s original description of the issue:
The Optimize Database after Deleting Revisions plugin for WordPress is vulnerable to Cross-Site Request Forgery in versions up to, and including, 5.0.110. This is due to missing or incorrect nonce validation on the ‘odb_start_manually’ function. This makes it possible for unauthenticated attackers to start the database optimization process via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.
This issue hasn’t been fixed, but if you look at the relevant entry now, Wordfence claims the vulnerability has been fixed.
Here is the new description:
The Optimize Database after Deleting Revisions plugin for WordPress is vulnerable to Cross-Site Request Forgery in versions up to, and including, 5.0.110. This is due to missing or incorrect nonce validation on the ‘odb_csv_download’ function. This makes it possible for unauthenticated attackers to trigger a download of the plugin’s data via a forged request granted they can trick a site administrator into performing an action such as clicking on a link.
They are describing two different issues.
For some reason, they replaced all the details, but kept the same entry. So they knew there was an unfixed vulnerability, but memory holed that.
The other problem with that is that the second issue isn’t really a CSRF issue.
Privilege Escalation Vulnerability
The change the developer made that they thought fixed the vulnerability was to remove functionality that allowed downloading a CSV of log data generated by the plugin. That functionality was accessible to anyone, even though only Administrators are able to access the plugin’s main functionality.
The reason why that was accessible to anyone is that it was registered to run during admin_init, which makes it accessible to everyone:
19 | add_action('admin_init', array(&$this, 'odb_csv_download')); |
And that there are no security checks done:
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | function odb_csv_download() { global $odb_class, $wpdb; if(isset($_REQUEST['action']) && $_REQUEST['action'] == 'odb_download_csv') { $export_keys = array( 'odb_id' => __('id', $odb_class->odb_txt_domain), 'odb_timestamp' => __('date', $odb_class->odb_txt_domain), 'odb_revisions' => __('deleted revisions', $odb_class->odb_txt_domain), 'odb_trash' => __('deleted trash', $odb_class->odb_txt_domain), 'odb_spam' => __('deleted spam', $odb_class->odb_txt_domain), 'odb_tags' => __('deleted tags', $odb_class->odb_txt_domain), 'odb_transients' => __('deleted transients', $odb_class->odb_txt_domain), 'odb_pingbacks' => __('deleted pingbacks', $odb_class->odb_txt_domain), 'odb_orphans' => __('deleted orphans', $odb_class->odb_txt_domain), 'odb_tables' => __('nr of optimized tables', $odb_class->odb_txt_domain), 'odb_before' => __('database size BEFORE', $odb_class->odb_txt_domain), 'odb_after' => __('database size AFTER', $odb_class->odb_txt_domain), 'odb_savings' => __('SAVINGS', $odb_class->odb_txt_domain) ); $this->sql = 'SELECT * FROM ' . $odb_class->odb_logtable_name . ' ORDER BY odb_id'; $items = $wpdb->get_results($this->sql, ARRAY_A); $this->odb_output_csv($export_keys, $items); |
While there isn’t a nonce check to prevent CSRF in the code, there really isn’t a CSRF vulnerability there, since all that an attacker could do is to cause someone else to download the data. The attacker can already download the data themselves. It doesn’t make sense that Wordfence would identify that as CSRF vulnerability, when the issue isn’t really that, but they did that.
CSRF Vulnerability
The remaining issue is that there isn’t a nonce check when running the optimization operations accessible from /wp-admin/tools.php?page=rvg-optimize-database.
When accessing that page, the function odb_start_manually() in the plugin’s main file is run and that, in turn, causes the function odb_start() to run. That doesn’t have a nonce check before doing actions like the clearing the aforementioned log:
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 | function odb_start($scheduler) { $this->odb_create_log_table(); // PAGE LOAD TIMER $time = microtime(); $time = explode(' ', $time); $time = $time[1] + $time[0]; $this->odb_start_time = $time; $action = ''; if(isset($_REQUEST['action'])) { $action = $_REQUEST['action']; // v4.6 if($action == 'view_log') { // SHOW THE LOGS $this->odb_logger_obj->odb_view_log(); // v4.6.1 return; } else if($action == "clear_log") { // CLEAR THE LOG TABLE $this->odb_logger_obj->odb_clear_log(); |
That is what Wordfence originally described as the vulnerability.
Avoiding Future Situation Like This
There are some fairly obvious ways this situation and future ones can be handled better, though considering that the security providers causing problems here don’t seem to care about all the problems they cause it seems unlikely they will change.
Security providers should provide the details of claimed vulnerabilities, so that they can be independently verified. Both Patchstack and Wordfence don’t currently do that. Worse still, they both try to get people to report vulnerabilities to them instead of more responsible parties that do provide that information.
Wordfence should hire people who can handle things better than they have now. It’s hard to understand what even happened with them swapping vulnerabilities, but it is far from the only problem. No one should be using their data unless they can get the problems fixed. Considering their track record, that seems unlikely.
Plugin developers should accept help offered to them. So often we find that developers are not properly fixing vulnerabilities and not taking advantage of offers of help to get them fixed. Leading to known vulnerabilities continue to be in plugins.
Proof of Concept for Privilege Escalation Vulnerability
The following proof of concept will download a CSV file of the data logged by the plugin.
Make sure to replace “[path to WordPress]” with the location of WordPress.
http://[path to WordPress]/wp-admin/admin-post.php?action=odb_download_csv
Proof of Concept for CSRF Vulnerability
The following proof of concept will cause the plugin’s log data to be cleared, when logged in to WordPress as an Administrator.
Make sure to replace “[path to WordPress]” with the location of WordPress.
http://[path to WordPress]/wp-admin/tools.php?page=rvg-optimize-database&action=clear_log