Update ASAP! Critical Unauthenticated Arbitrary File Upload in MW WP Form Allows Malicious Code Execution

🎁 Wordfence just launched its bug bounty program. Through December 20th 2023, all researchers will earn 6.25x our normal bounty rates when Wordfence handles responsible disclosure for our Holiday Bug Extravaganza! Register as a researcher and submit your vulnerabilities today!🎁


On November 24, 2023, the Wordfence Threat Intelligence team identified and began the responsible disclosure process for an Unauthenticated Arbitrary File Upload vulnerability in MW WP Form plugin, which is actively installed on more than 200,000 WordPress websites. This vulnerability makes it possible for an unauthenticated attacker to upload arbitrary files, including PHP files, and achieve remote code execution on a vulnerable site’s server when the “Saving inquiry data in database” option in the form settings is enabled.

All Wordfence PremiumWordfence Care, and Wordfence Response customers, as well as those still using the free version of our plugin, are protected against any exploits targeting this vulnerability by the Wordfence firewall’s built-in Malicious File Upload protection.

We contacted the Web-Soudan Team on November 24, 2023, and received a response the same day. After providing full disclosure details, the developer released a patch on November 29, 2023. We would like to commend The Web-Soudan Team for their prompt response and timely patch.

We urge users to update their sites with the latest patched version of MW WP Form, which is version 5.0.2 at the time of this writing, as soon as possible.

Vulnerability Summary from Wordfence Intelligence

Description: MW WP Form <= 5.0.1 – Unauthenticated Arbitrary File Upload
Affected Plugin: MW WP Form
Plugin Slug: mw-wp-form
Affected Versions: <= 5.0.1
CVE ID: CVE-2023-6316
CVSS Score: 9.8 (Critical)
CVSS Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Researcher/s: István Márton
Fully Patched Version: 5.0.2

The MW WP Form plugin for WordPress is vulnerable to arbitrary file uploads due to insufficient file type validation in the ‘_single_file_upload’ function in versions up to, and including, 5.0.1. This makes it possible for unauthenticated attackers to upload arbitrary files on the affected site’s server which may make remote code execution possible.

Technical Analysis

The MW WP Form plugin provides a shortcode-based form builder, with many customizable fields and many useful form options. Files can also be uploaded to the form with the [mwform_file name="file"] shortcode field.

Examining the code reveals that the plugin uses the _single_file_upload() function in the MW_WP_Form_File class to file upload, and the check_file_type() function in the MWF_Functions class is used to check the file type.

class MWF_Functions {
/**
 * Return true when correct file type.
 *
 * @param string $filepath Uploaded file path.
 * @param string $filename File name.
 * @return bool
 */
public static function check_file_type( $filepath, $filename = '' ) {
	if ( ! file_exists( $filepath ) ) {
		return false;
	}

	// File type restricted by WordPress (get_allowed_mime_types)
	if ( $filename ) {
		$wp_check_filetype = wp_check_filetype( $filename );
	} else {
		$wp_check_filetype = wp_check_filetype( $filepath );
	}
	if ( empty( $wp_check_filetype['type'] ) ) {
		return false;
	}

This is a completely common and safe file type checking function that uses the WordPress core function.

class MW_WP_Form_File {
protected function _single_file_upload( $form_id, $name, $file ) {
	if ( empty( $file['tmp_name'] ) ) {
		return false;
	}

	$error = $file['error'];

	try {
		if ( UPLOAD_ERR_OK !== $error && UPLOAD_ERR_NO_FILE !== $error ||
			! MWF_Functions::check_file_type( $file['tmp_name'], $file['name'] ) ) {
			if ( UPLOAD_ERR_INI_SIZE === $error || UPLOAD_ERR_FORM_SIZE === $error ) {
				throw new \RuntimeException( '[MW WP Form] File size of the uploaded file is too large.' );
			}
			throw new \RuntimeException( '[MW WP Form] An error occurred during file upload.' );
		}
	} catch ( \Exception $e ) {
		error_log( $e->getMessage() );
	}

	try {
		$new_user_file_dir = MW_WP_Form_Directory::generate_user_file_dirpath( $form_id, $name );
		if ( ! wp_mkdir_p( $new_user_file_dir ) ) {
			throw new \RuntimeException( '[MW WP Form] Creation of a temporary directory for file upload failed.' );
		}
	} catch ( \Exception $e ) {
		error_log( $e->getMessage() );
	}

	MW_WP_Form_Directory::do_empty( $new_user_file_dir, true );

	$filename = sanitize_file_name( sprintf( '%1$s-%2$s', $name, $file['name'] ) );
	$filepath = MW_WP_Form_Directory::generate_user_filepath( $form_id, $name, $filename );

	try {
		if ( ! move_uploaded_file( $file['tmp_name'], $filepath ) ) {
			throw new \RuntimeException( '[MW WP Form] There was an error saving the uploaded file.' );
		}
	} catch ( \Exception $e ) {
		error_log( $e->getMessage() );
	}

	return $filename;
}

The upload function checks the file and then copies it to the server with the move_uploaded_file() function. The file is only stored on the server if the “Saving inquiry data in database” option is selected in the form settings. Otherwise the file is immediately deleted after submitting the form.

Unfortunately, although the file type check function works perfectly and returns false for dangerous file types, it throws a runtime exception in the try block if a disallowed file type is uploaded, which will be caught and handled by the catch block. The catch block only uses the error_log() function to log the error without interrupting the upload. This means that even if the dangerous file type is checked and detected, it is only logged, while the function continues to run and the file is uploaded. This means that attackers could upload arbitrary PHP files and then access those files to trigger their execution on the server, achieving remote code execution.

We would like to draw attention once again to the fact that the vulnerability only critically affects users who have enabled the “Saving inquiry data in database” option in the form settings, because the plugin only saves the files in this configuration.

Disclosure Timeline

November 24, 2023 – Discovery of the Arbitrary File Upload vulnerability in MW WP Form.
November 24, 2023 – We initiate contact with the plugin vendor asking that they confirm the inbox for handling the discussion.
November 24, 2023 – The vendor confirms the inbox for handling the discussion.
November 24, 2023 – We send over the full disclosure details. The vendor acknowledges the report and begins working on a fix.
November 29, 2023 – A fully patched version of the plugin, 5.0.2, is released.

Conclusion

In this blog post, we detailed an Arbitrary File Upload vulnerability within the MW WP Form plugin affecting versions 5.0.1 and earlier. This vulnerability allows unauthenticated threat actors to upload arbitrary files, including PHP backdoors, and execute those files on the server. The vulnerability has been fully addressed in version 5.0.2 of the plugin.

We encourage WordPress users to verify that their sites are updated to the latest patched version of MW WP Form.

All Wordfence users, including those running Wordfence PremiumWordfence Care, and Wordfence Response, as well as sites still running the free version of Wordfence, are fully protected against this vulnerability.

If you know someone who uses this plugin on their site, we recommend sharing this advisory with them to ensure their site remains secure, as this vulnerability poses a significant risk.

Did you know that Wordfence has a Bug Bounty Program? We’ve recently increased our bounties by 6.25x until December 20th, 2023, with our bounties for the most critical vulnerabilities reaching $10,000 USD! If you’re an aspiring or current vulnerability researcher, click here to sign up.

Did you enjoy this post? Share it!

Comments

No Comments