Critical Vulnerability Patched in WooCommerce Upload Files

On December 29, 2020, the Wordfence Threat Intelligence team was alerted to a potential 0-day vulnerability in the WooCommerce Upload Files plugin, an add-on for WooCommerce with over 5,000 installations.

Please note that this is a separate plugin from the main WooCommerce plugin and is designed as an add-on to that plugin.

After confirming the vulnerability, we contacted the plugin’s developer, Domenico Lagudi, who responded quickly and released a patch the same day, on December 29, 2020.

Although the Wordfence firewall’s built-in rules provided some degree of protection against this vulnerability, we determined that a bypass was possible. We quickly released a firewall rule to our premium customers on December 29, 2020. Sites still running the free version of Wordfence received the firewall rule 30 days later, on January 28, 2021.

Description: Unauthenticated Arbitrary File Upload
Affected Plugin: WooCommerce Upload Files
Plugin Slug: woocommerce-upload-files
Affected Versions: < 59.4
CVE ID: CVE-2021-24171
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
Fully Patched Version: 59.4

WooCommerce Upload Files is a premium plugin designed to allow customers to upload files when checking out in order to purchase customized products. In order to provide this functionality, it uses a publicly accessible AJAX function, ajax_manage_file_chunk_upload.

	function ajax_manage_file_chunk_upload()
	{
		global $wcuf_session_model ;
		
		if(!isset($_POST['wcuf_upload_field_name']))
			wp_die();
		
		$this->saving_on_session = true;
		$buffer = 5242880; //1048576; //1mb
		$target_path = $this->get_temp_dir_path();
		$tmp_name = $_FILES['wcuf_file_chunk']['tmp_name'];
		$size = $_FILES['wcuf_file_chunk']['size'];
		$current_chunk_num = $_POST['wcuf_current_chunk_num'];
		$file_name = str_replace($this->to_remove_from_file_name, "",$_POST['wcuf_file_name']);
		$tmp_file_name = $_POST['wcuf_current_upload_session_id']."_".$file_name;
		$upload_field_name = str_replace($this->to_remove_from_file_name, "", $_POST['wcuf_upload_field_name']);
		$wcuf_is_last_chunk = $_POST['wcuf_is_last_chunk'] == 'true' ? true : false;
	
		$com = fopen($target_path.$tmp_file_name, "ab");
		$in = fopen($tmp_name, "rb");
			if ( $in ) 
				while ( $buff = fread( $in, $buffer ) ) 
				   fwrite($com, $buff);
				 
			fclose($in);
		fclose($com);
		
		wp_die();
	}

File names were based on a combination of an optional wcuf_current_upload_session_id parameter and the wcuf_file_name parameter. While the function did attempt to prevent the upload of files with executable extensions, it did so by checking the filename supplied in the wcuf_file_name parameter against a list of dangerous extensions and then removing the extension from the filename rather than blocking the request.

	var $to_remove_from_file_name = array(".php", "../", ".jsp", ".vbs", ".exe", ".bat", ".php5", ".pht", ".phtml", 
										  ".shtml", ".asa", ".cer", ".asax", ".swf", ".xap", ";", ".asp", ".aspx",
										  "*", "<", ">", "::");

For instance, uploading a file with a wcuf_current_upload_session_id parameter set to session1 and the wcuf_file_name parameter set to shell.php would result in the actual file uploaded being named session1_shell as the .php extension would be removed. The function only ran the sanitization process a single time, so it could be bypassed by sending a filename containing a blocked extension hidden inside another blocked extension. For example, if an attacker uploaded a file with the wcuf_current_upload_session_id parameter set to session1 and the wcuf_file_name set to shell.p.phphp, the middle .php would be removed, leaving the final file name as session1_shell.php.

Unfortunately, the wcuf_current_upload_session_id parameter was also not sufficiently sanitized and was vulnerable to directory traversal. For instance, if a request was sent with the wcuf_current_upload_session_id parameter set to ../../../../file and the wcuf_file_name set to info.p.phphp, the resulting file would be named file_info.php and would end up in the webroot.

This also meant that a double extension attack was possible. For instance, setting the wcuf_file_name parameter to test and the wcuf_current_upload_session_id parameter to info.php. would result in a filename of info.php._test which would be executable in Apache environments that use an AddHandler directive for PHP files.

Regardless of the method used, an attacker able to upload an executable PHP file to a website using this method would be able to infect and completely take over that website, as well as any other sites on the same hosting account.

Be Careful With Input Sanitization

As more WordPress developers focus on security, simple vulnerabilities are becoming less common. While most developers are aware of the importance of sanitizing input, it’s also important to use the right functions for the right input, otherwise sanitization can actually be used to bypass security functionality. It’s important to understand the kind of input a function is expecting and the dangers it can pose. For example, a function designed to sanitize input to be used in a database query might not offer sufficient protection against Cross-Site Scripting(XSS), while a function designed to remove scripting tags might not offer protection against SQL Injection(SQLi). As a general rule, it’s better to block malicious input entirely than to try to clean it up with the wrong function.

Timeline

December 29, 2020
08:25 MST – Wordfence Threat Intelligence becomes aware of a potential 0-day in the WooCommerce Upload Files plugin.
09:09 MST – We find the vulnerable code and develop a proof of concept exploit.
09:48 MST – We write a firewall rule to block the exploit and begin testing.
10:36 MST – We initiate contact with the plugin developer.
11:10 MST – The plugin developer responds, and we provide full disclosure.
13:33 MST – The plugin developer releases a patched version.
18:09 MST – Our firewall rule passes final tests and is released to Wordfence Premium customers.

January 28, 2021
The firewall rule becomes available to free Wordfence users.

Conclusion

In today’s article, we detailed a critical 0-day vulnerability in the WooCommerce Upload Files plugin that would have allowed attackers to infect and completely take over a website. This vulnerability has been patched in version 59.4, and we recommend that all users update to the latest version of the plugin as soon as possible, which is 60.1 at the time of this writing.

Wordfence Premium users have been protected against this vulnerability since December 29, 2020, while sites still running the free version of Wordfence received the same protection on January 28, 2021.

If you know a friend or colleague who is using this plugin on their site, we highly recommend forwarding this advisory to them to help keep their sites protected as this is a critical severity issue that can result in remote code execution and site takeover.

Special thanks to plugin developer Domenico Lagudi for an extremely rapid response and to Threat Analyst Greg Bloom for his assistance getting a firewall rule deployed during holiday hours.

The post Critical Vulnerability Patched in WooCommerce Upload Files appeared first on Wordfence.

More great articles

Wordfence Intelligence Weekly WordPress Vulnerability Report (May 1, 2023 to May 7, 2023)

Last week, there were 58 vulnerabilities disclosed in 43 WordPress Plugins and 3 WordPress themes that have been added to…

Read Story

Wordfence Intelligence Weekly WordPress Vulnerability Report (October 7, 2024 to October 13, 2024)

Calling all superheroes and haunters! Introducing the Cybersecurity Month Spooktacular Haunt and the WordPress Superhero Challenge for the Wordfence Bug…

Read Story

Widespread Attacks Continue Targeting Vulnerabilities in The Plus Addons for Elementor Pro

Over the past 10 days, Wordfence has blocked over 14 million attacks targeting Privilege Escalation Vulnerabilities in The Plus Addons…

Read Story

Emergency WordPress Help

One of our techs will get back to you within minutes.