7 Sep 2023

WPMU DEV and Their Partner Patchstack Didn’t Handle Security Vulnerability in 400,000+ Install Plugin Well

WPMU DEV is a WordPress plugin developer that we have noted in the past hasn’t been handling security well despite being a security provider. They offer the Defender plugin, which WordPress says has 90,000+ installs. WPMU DEV claims that the pro version of that has 300,000+ installs. If you head to the homepage for the pro version right now, they claim to provide “reliable WordPress security”, which is powered by Patchstack:

Recently there was a serious vulnerability that was disclosed in WPMU DEV’s Forminator plugin, which has 400,000+ installs. You wouldn’t know that from the changelog for the version fixing it, which only says “New: PDF Generator add-on in Pro Version”.

Patchstack has an entry for it, where it claims it was “publicly disclosed” on August 29 (that is also the day they started warning about this):

Yet, if you click on the linked “vulnerability details” (form Mehmet Kelepçe), you find it was disclosed on August 4.

The version that fixed this was released on August 16.

So the developer took 12 days after it was publicly disclosed to fix the vulnerability.

Patchstack only warned about this 25 days after it was disclosed and 13 days after it had been fixed. What is supposed to be the value of that?

Maybe Patchstack is trying to cover up their partner’s and their own failure to handle this in a timely manner, by listing this as being publicly disclosed 25 days after it was. Or maybe it is just another example of their lack of concern for accuracy.

What Went Wrong?

The vulnerability in the plugin allowed arbitrary files to be uploaded, which is a type of vulnerability highly likely to be exploited, as a hacker can take control of the website through that. How did a plugin with 400,000+ installs contain such a vulnerability?

In digging into this, we found that the vulnerability has been in the plugin since it was introduced to the WordPress Plugin Directory in September 2018. The version number for the first version there is 1.5.1, suggesting this may have existed before it was in the plugin directory. How was this not caught before now?

The vulnerability involved the function upload_post_image() in the file /library/fields/postdata.php. In the version that fixed this, the following line was moved further into the function:

file_put_contents( $file, $file_data );

That line saves an uploaded file to the website’s filesystem.

Looking at that in the context of the code around in the last vulnerable version shows a big problem:

786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
public function upload_post_image( $field, $field_name ) {
	$post_image = self::get_property( 'post_image', $field, '' );
 
	if ( empty( $post_image ) ) {
		return true;
	}
	if ( ! empty( $_FILES[ $field_name ]['name'] ) ) {
		$file_name = sanitize_file_name( $_FILES[ $field_name ]['name'] );
		// TODO: refactor upload to use WP filesystem api.
		$file_data        = file_get_contents( $_FILES[ $field_name ]['tmp_name'] );
		$upload_dir       = wp_upload_dir(); // Set upload folder.
		$unique_file_name = wp_unique_filename( $upload_dir['path'], $file_name );
		$filename         = basename( $unique_file_name ); // Create base file name.
 
		if ( wp_mkdir_p( $upload_dir['path'] ) ) {
			$file = $upload_dir['path'] . '/' . $filename;
		} else {
			$file = $upload_dir['basedir'] . '/' . $filename;
		}
 
		// Create the  file on the server.
		file_put_contents( $file, $file_data );
 
		// Check image file type.
		$wp_filetype = wp_check_filetype( $filename, null );
		$image_exts  = apply_filters( 'forminator_field_postdata_image_file_types', $this->image_extensions );
		if ( in_array( (string) $wp_filetype['ext'], $image_exts, true ) ) {

There is a check to limit what types of files can be processed by the code, but that only occurs right after the file is saved to the website. The new version moves the line after the file type check:

809
810
811
812
		if ( in_array( (string) $wp_filetype['ext'], $image_exts, true ) ) {
 
			// Create the  file on the server.
			file_put_contents( $file, $file_data );

It’s unclear to us if the line was intended to have been further into the code or if the code was written intended to be written as it was and the developer wasn’t aware it would be an issue.

Another issue here is that the code we just showed runs even when the relevant field type of the plugin isn’t configured in a form. That seems like it should be dealt with as well.

How Could This Vulnerability Have Been Fixed Sooner?

A good security review of the plugin should have caught this. Unfortunately, very few plugins go through such a review.

Based on what we have seen over the years, plugins from security providers, like WPMU DEV, are not going through those types of reviews. Last year, another partner of Patchstack’s, iThemes Security (now Solid Security), had a vulnerability in another of their plugins found and exploited by a hacker. That was a vulnerability that would have been caught by a security review. Patchstack has a history of partnering with security providers who are not handling security well. It seems like avoiding anyone who would get involved with Patchstack would be good security advice.

Another way to have addressed the most serious element of this (the lack of restriction on what types of files can be uploaded), was something we touched on in a post we wrote in November on avoiding arbitrary file upload vulnerabilities:

The best approach, if possible, is to rely on WordPress function for handling file uploads wp_handle_upload(), as that has various built-in security checks.

That still hasn’t been done here.

Failure to Protect Against Vulnerability

The start of the description of the Defender plugin on the WordPress Plugin Directory makes it sound like it should protect against this vulnerability (emphasis WPMU DEV’s):

Defender adds the best in WordPress plugin security to your website with just a few clicks. Stop brute force login attacks, SQL injections, cross-site scripting XSS, and other WordPress vulnerabilities and hacks with Defender’s malware scanner, antivirus scans, IP blocking, firewall, activity log, security log, and two-factor authentication (2FA) login security.

No longer do you have to go through hideously complex security settings and get a virtual PhD in security. Defender adds all the hardening and security recommendations you need.

Based on past testing we have done, several WordPress security plugins should be able to protect against this vulnerability being exploited. So surely Defender does? We tested it out and found that it didn’t. We then tested our own Plugin Vulnerabilities Firewall and confirmed that, as expected, it did protect against this. So security plugins can protect against this, but Defender, doesn’t.


Plugin Security Scorecard Grade for Forminator

Checked on November 28, 2024
F

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


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. Required fields are marked *