13 Nov 2023

Exploited Vulnerability in WordPress Plugin Shows Importance of Robust Firewall Protection

Over the weekend, we had an attacker try to exploit a local file inclusion (LFI) vulnerability that was recently fixed in the WordPress plugin Blog Designer Pack on our website. We are not running the plugin, so we were not risk. But our own firewall plugin still blocked the exploit attempts through its protection against directory traversal:

That wouldn’t be the case with many other firewall plugins, even ones that have protection against that type of attack. We touched on the limited protection those provide against directory traversal in a previous post, discussing the very limited protection offered by a plugin that recently added firewall capability, while looking at our monthly firewall zero-day protection test results. We will now expand on that and then explain how the vulnerability in the plugin resulted from a security issue that WordPress’ plugin directory could be warning plugin developers about.

Firewall Plugins Not Checking All Input

Directory traversal involves instructing that a file in a different file directory than the currently specified one is accessed. That commonly involves instructing to move to a higher directory, which looks like this: “../”. From the data logged, when our firewall plugin stopped the attack attempt, the directory traversal in the request was in POST input. That is additional data sent with a request.

Of the 18 WordPress firewall plugins that we test, 8 of them have some protection against directory traversal protection. All 8 will block a request if the “../” is included in the URL, otherwise known GET input. Only three of them will block a request if it is in the POST input. Those plugins Anti-Malware Security and Brute-Force Firewall, our Plugin Vulnerabilities Firewall, and Wordfence Security. So only 3 of 18 plugins would have blocked this attack attempt. That isn’t a good result.

What makes that result stand out more is that Anti-Malware Security and Brute-Force Firewall is among the worst performing plugins in our monthly zero-day protection testing. Coming in tenth place and only blocking 4.0% of the test earlier this month. While our Plugin Vulnerabilities Firewall came in first, while blocking 100%, and Wordfence Security came in third, blocking 23.2%. That speaks to the haphazard nature of the protection offered by most firewall plugins, which have developers that are not doing systematic testing to provide robust protection.

The directory traversal protection results are even worse with other variants of this type of issue. Only our Plugin Vulnerabilities Firewall and Wordfence Security block directory traversal formatted for Windows servers. Only our plugin blocks attempt involving data sent with the JSON content type.

The Vulnerability and extract() Usage

The changelog for the latest version of the Blog Designer Pack plugin reads, “Update Load More functionality with better security.” Looking at the changes made, it is possible to see what the requests being blocked were trying to access.

The requests were calling an AJAX action registered to “bdp_get_more_post”. That registration occurs in the file /includes/bdp-ajax-functions.php, where that is made accessible to those logged in to WordPress, as well as those not logged in:

18
19
add_action( 'wp_ajax_bdp_get_more_post', array($this, 'bdp_get_more_post') );
add_action( 'wp_ajax_nopriv_bdp_get_more_post', array($this, 'bdp_get_more_post') );

That in turns calls the function bdp_get_more_post(), which was one of the files changed in the latest version. This is the beginning of that function, as of the previous version of the plugin:

27
28
29
30
31
32
33
34
35
36
37
38
function bdp_get_more_post() {
 
	// Taking some defaults
	$result = array();
 
	if( !empty($_POST['shrt_param']) ) {
 
		global $post, $bdp_in_shrtcode;
 
		extract( $_POST['shrt_param'] );
		exit($design );
		$design_file_path 	= BDP_DIR . '/templates/masonry/' . $design . '.php';

That code passes user input in the form of POST input to the extract() function. The PHP documentation for that function has a warning that reads “Do not use extract() on untrusted data, like user input (e.g. $_GET, $_FILES).” WordPress’ own coding standards go further and say “Don’t extract()“. WordPress could warn developers of insecure usage of extract() like that. It is something our own Plugin Security Checker already flags.

The practical implication of that extract() usage is the code allows an attacker to replace the value of the variable $design. That variable is used to partially specify a file location, which is then included (or loaded) later in the code:

87
include( $design_file );

Through directory traversal, an attacker can specify files outside of the intended directory to be included. Looking back at the blocked requests, the directory traversal was in relevant POST input.

One of the attempts appeared to be trying to take advantage of that with what appears to have been a security issue in server software, which would allow code sent by the attacker to run.

The new version removes the usage of extract(), which removes the vulnerability.

Protecting Against Other Vulnerabilities Like This

In this case, the vulnerability was already fixed at the time of those attacks, so simply keeping WordPress plugins up to date would protect against this. That is the best approach if vulnerabilities have actually been fixed. But what about in other situations?

Oftentimes, we find that vulnerabilities that were supposed to have been fixed haven’t been, so it is important to either check that it has been fixed yourself or, more likely, rely on someone else that will do that for you. The latter option turns out to be hard, as many supposed experts are not actually doing the work they claim to do to verify things, even with the most serious vulnerabilities.

With vulnerabilities that are not publicly known about, there are two options.

One is to catch the vulnerability before hackers start exploiting it. Considering that an automated tool was able to flag the insecure usage of extract() a good security review of the plugin should have caught the issue. It appears that the plugin had not had one for quite a while, as the vulnerability had existed from April 2018 until last month. A security review either requires security expertise or being able to hire someone with that expertise, which isn’t something everyone has access to.

The other option is to use a firewall plugin, as those have the possibility of stopping a lot of zero-day attacks. Which is an attack against a vulnerability not known to the developer. The problem, as we discussed above, is that most of those have very limited protection. So it is important to use a plugin that provides robust protection.

Leave a Reply

Your email address will not be published. Required fields are marked *