2 Oct 2023

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

Plugin Security Scorecard Grade for Patchstack

Checked on March 5, 2025
D

See issues causing the plugin to get less than A+ grade

Leave a Reply

Your email address will not be published.