7 Aug 2023

Code That Leads to Arbitrary File Upload Vulnerability in StellarWP’s Kadence Blocks Has Been There for 5 Months

A couple of weeks ago, we noted how Wordfence had claimed that a lack of newly introduced vulnerabilities being detected in WordPress plugins was proof that the security of plugins was improving, but it could actually be that detection of newly introduced vulnerabilities isn’t very good. A serious vulnerability that recently became functional in the 300,000+ install plugin Kadence Blocks is further evidence of poor detection of newly introduced vulnerabilities.

The developer of that plugin, StellarWP, has had a terrible security track record despite developing one of the most popular security plugins. Including failing to fix a vulnerability that their security plugin was warning about and failing to implement basic security in another plugin, leading to a zero-day. That makes the issue with Kadence Blocks not all that surprising.

On February 21, version 3.0.9 of the plugin was released. Code we will show in a bit was flagged by our proactive monitoring of changes made to plugins in the Plugin Directory to try to catch serious vulnerabilities. It looked like it contained a serious vulnerability, but it turned out it wasn’t accessible. Version 3.1 was supposed to be released in less than a month, which seemed like it would enable the relevant feature that uses the code. Less than a month turned in to over 5 months. Even then, the intended functionality didn’t work. It only became functional in version 3.1.8, which was released several days later.

Once it worked, we could easily confirm there is a serious vulnerability.

We tested and confirmed that our firewall plugin for WordPress protected against exploitation of this vulnerability, even before we confirmed that it existed, as part of its protection against zero-day vulnerabilities.

Arbitrary File Upload

Version 3.1 introduces an Advanced Form Block, which provides the option to allow uploading files. Insecure handling of file uploads is one of the most likely to be exploited security issues in a WordPress plugins, so great care should be made in implementing that. That isn’t the case with Kadence Blocks.

The code that handles the file upload is located in the function process_fields() now in the file /includes/advanced-form/advanced-form-ajax.php (and previously in the file /includes/advanced-form-ajax.php). That doesn’t use WordPress’ built-in functions to handle the upload process. WordPress’ functionality is hardened against various means of abuse. Instead, it uses the following code to try to limit what types of files can be uploaded:

265
266
267
268
269
270
271
272
$allowed_file_categories = empty( $field['allowedTypes'] ) ? array( 'images' ) : $field['allowedTypes'];
$allowed_file_types      = $this->get_allowed_mine_types( $allowed_file_categories );
 
$mime_type = mime_content_type( $_FILES[ $expected_field ]['tmp_name'] );
 
if ( ! in_array( $mime_type, $allowed_file_types ) ) {
	$this->process_bail( __( 'Submission Failed', 'kadence-blocks' ), __( 'File type not allowed', 'kadence-blocks' ) );
}

That checks if the file has a MIME type – as determined by the function mime_content_type() – that is allowed. The allowed MIMEs are determined by the function get_allowed_mine_types(). By default, that allows several image MIME types:

413
414
415
416
417
'images'     => array(
	'image/gif',
	'image/jpeg',
	'image/png',
),

The problem with that code is that it is easy to cause mime_content_type() to report that a file is a GIF file, which is permitted when it isn’t. As confirmed with the proof of concept below, an attacker can upload a file containing malicious PHP code through this upload functionality, giving them complete control over the website.

The only restriction on accessing an uploaded file is that the time it was uploaded is appended to the file name:

287
288
289
290
291
292
293
294
295
296
297
298
299
$subfolder     = '/kadence_form/' . date( 'Y' ) . '/' . date( 'm' ) . '/';
$destination   = wp_upload_dir()['basedir'] . $subfolder;
 
$upload_filename = wp_unique_filename( $destination, time() . '_' . $_FILES[ $expected_field ]['name'] );
$abs_file_path = $destination . $upload_filename;
$rel_file_path = '/uploads' . $subfolder . $upload_filename;
 
// Create folder if not exist
if ( ! is_dir( $destination ) ) {
	wp_mkdir_p( $destination );
}
 
if ( move_uploaded_file( $_FILES[ $expected_field ]['tmp_name'], $abs_file_path ) ) {

WordPress Causes Full Disclosure

As a protest of the moderators of the WordPress Support Forum’s continued inappropriate behavior we changed from reasonably disclosing to full disclosing vulnerabilities for plugins in the WordPress Plugin Directory in protest, until WordPress gets that situation cleaned up, so we are releasing this post and then leaving a message about that for the developer through the WordPress Support Forum. (For plugins that are also in the ClassicPress Plugin Directory, we will follow our reasonable disclosure policy.)

You can notify the developer of this issue on the forum as well.

After four years, the moderators have finally tacitly admitted they were behaving inappropriately and have made moves to fix the problems (though incompletely), so these full disclosures can be ended if they simply restore access to our accounts and plugins in the Plugin Directory. Hopefully that takes less than four years.

Proof of Concept

Create new a form for the plugin (/wp-admin/post-new.php?post_type=kadence_form) with a File field (located in the Advanced Fields). Add that to a post or page.

Submit that form with a file with the .php extension that begins “GIF89a”. That file will be successfully uploaded at a location specified by the code above.


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 Kadence Blocks

Checked on January 23, 2025
F

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

Leave a Reply

Your email address will not be published.