On July 23, 2020, our Threat Intelligence team discovered a vulnerability present in two themes by Elegant Themes, Divi and Extra, as well as Divi Builder, a WordPress plugin. Combined, these products are installed on an estimated 700,000 sites. This flaw gave authenticated attackers, with contributor-level or above capabilities, the ability to upload arbitrary files, including PHP files, and achieve remote code execution on a vulnerable site’s server.
We initially reached out to Elegant Themes on July 23, 2020 and, after establishing an appropriate communication channel, we provided the full disclosure details on July 28, 2020. The developers responded on June 29, 2020 to let us know a patch would be coming in the next version. Patches were released yesterday, on August 3, 2020, in version 4.5.3 for all products.
This is considered a critical security issue that could lead to remote code execution on a vulnerable site’s server. If you haven’t already updated, and you are running Divi versions 3.0 and above, Extra versions 2.0 and above, or Divi Builder versions 2.0 and above, we highly recommend updating to the patched version, 4.5.3 , immediately. Alternatively, you can use their Security Patcher Plugin until you can update safely.
Both Wordfence Premium and free users are protected against any attacks attempting to exploit this vulnerability due to the Wordfence firewall’s built-in malicious file upload protection.
Elegant Themes is the creator behind one of the most popular premium themes, Divi. One of the features of the Divi theme is that it comes with the Divi Page Builder that makes the site design and editing process easy and customizable. In addition to the Divi theme, Elegant Themes offers an alternative theme, Extra, that includes the Divi Builder. The standalone Divi Builder plugin is also available and can be used with any theme.
As part of the Divi Builder functionality, users that have the ability to create posts can import and export Divi page templates using the portability feature.
Divi Builder portability feature used to import layouts
What went wrong?
Taking a closer look at the code, we can see that the portability
import function was triggered with the use of the
et_core_portability_import AJAX action and corresponding
et_core_portability_ajax_import function, which does have nonce and capability check.
add_action( 'wp_ajax_et_core_portability_import', 'et_core_portability_ajax_import' );
The core of the problematic code could be found within the
import function of the builder’s
public function import( $file_context = 'upload' )
self::$_doing_import = true;
$timestamp = $this->get_timestamp();
$filesystem = $this->set_filesystem();
$temp_file_id = sanitize_file_name( $timestamp );
$temp_file = $this->has_temp_file( $temp_file_id, 'et_core_import' );
$include_global_presets = isset( $_POST['include_global_presets'] ) ? wp_validate_boolean( $_POST['include_global_presets'] ) : false;
$global_presets = '';
if ( $temp_file )
$import = json_decode( $filesystem->get_contents( $temp_file ), true );
if ( ! isset( $_FILES['file'] ) )
if ( ! in_array( $file_context, array( 'upload', 'sideload' ) ) )
$file_context = 'upload';
Analyzing the code further, we see that the file is temporarily uploaded using
test_type set to false, overriding the
wp_check_filetype_and_ext function that checks a file’s type and determines if it is a safe file to upload based on a list of allowed mime types.
This meant that the
wp_handle_upload function did not test the file type during the upload, essentially disabling the extensive file-type checking protection built-in to the function.
$handle_file = "wp_handle_$file_context";
$upload = $handle_file( $_FILES['file'], array(
'test_size' => false,
'test_type' => false,
'test_form' => false,
do_action( 'et_core_portability_import_file', $upload['file'] );
From there, the file’s content was checked to see if it could be used for the import. If the file’s content did not appear to be usable JSON data for an import, then the process was killed and the message
‘importContextFail’ was returned.
$temp_file = $this->temp_file( $temp_file_id, 'et_core_import', $upload['file'] );
$import = json_decode( $filesystem->get_contents( $temp_file ), true );
$import = $this->validate( $import );
$import['data'] = $this->apply_query( $import['data'], 'set' );
if ( ! isset( $import['context'] ) || ( isset( $import['context'] ) && $import['context'] !== $this->instance->context ) )
return array( 'message' => 'importContextFail' );
Toward the end of the function, there was a hook to the function
‘delete_temp_files’ that was intended to delete any JSON files used for the import once completed. However, since the import died for files without usable JSON content before getting to this function, the files remained in the uploads directory until a legitimate JSON file was imported.
$this->delete_temp_files( 'et_core_import' );
This flaw made it possible for authenticated users with the
edit_posts capability, like contributors, editors, and authors, to upload arbitrary files. An attacker could easily upload malicious PHP files and access them from the uploads directory. This could ultimately result in remote code execution and complete compromise of a vulnerable site’s hosting account.
wp_ajax_et_theme_builder_api_import_theme_builder AJAX action and corresponding function used to import a theme builder template was also susceptible to arbitrary file uploads due to the same issues, however, exploiting this would have required administrative privileges thus significantly reducing it’s severity.
Fortunately, Elegant Themes was very quick to respond and release a patch that not only prevented all files except .json files from being uploaded, but also ensured that files would be sufficiently deleted at any stage of the process once no longer used.
How to Update your Elegant Themes Product
As long as you have supplied your Elegant Themes Username and API key on your WordPress site, then you can take care of your updates directly in the updates area on your site. To do so, log into your site, and navigate to the “Updates” area. Select the Elegant Themes product you would like to update and just click “Update Plugin” or “Update Theme” depending on which product you are updating.
Also, please note that Elegant Themes has made this patch available to users, even if your account is expired.
WordPress updates area with Divi Builder plugin that needs updated.
If you are unable to update fully, you can install Elegant Themes Security Patcher Plugin that will temporarily patch the vulnerability until you are able to do a complete update.
Another way to stay protected
As mentioned, in our post last week, Wordfence has a feature to disable code execution in the uploads directory. Even if you’re not using one of Elegant Themes’ vulnerable products, we highly recommend enabling this setting as it will provide additional protection against vulnerabilities like this one that may erroneously allow PHP files to be uploaded into the uploads directory.
With this option enabled, attackers will not be able to execute PHP files uploaded into the uploads directory, providing an extra layer of security and assisting in thwarting attacks like this one. In the event that a zero-day vulnerability is discovered and actively exploited prior to the creation of a custom firewall rule, having this feature enabled can help keep your site protected.
The ‘Disable Code Execution for Uploads directory’ option location.
Proof of Concept Walkthrough
Due to the critical severity of this vulnerability and high user install base, we are refraining from posting a proof of concept walkthrough video for this vulnerability at this time. If you are interested to learn how this vulnerability might be exploited, please join us for Wordfence Office Hours next week on Tuesday, August 11th at 12:00 EST. This allows us to give you time to update and still provide you with the in-depth details on how this could have been exploited on unprotected sites.
Jul 23, 2020 – Initial discovery of vulnerability. We verify the Wordfence firewall provides protection against exploit attempts and we make our initial contact attempt with the Elegant Themes team.
July 27, 2020 – The developer confirms inbox for handling disclosure.
July 28, 2020 – We send full disclosure details.
July 28, 2020 – They respond letting us know they have begun working on a patch and anticipate releasing it on the upcoming Monday.
July 31, 2020 – They send us the details of the patch so we can verify the fix is sufficient.
August 3, 2020 – A patch is released in version 4.5.3 for all products.
In today’s post, we detailed a flaw in Elegant Themes’ products Divi, Extra, and Divi Builder that provided authenticated users with the ability to upload arbitrary files, including PHP files, and execute any code in those files on the server. This flaw has been fully patched in version 4.5.3 for all products. We recommend that users immediately update to the latest version available, which is version 4.5.3 at the time of this publication.
Sites using Wordfence Premium as well as those still using the free version of Wordfence are protected from attacks against this vulnerability. If you know a friend or colleague who is using one of these themes or the plugin on their site, we highly recommend forwarding this advisory to them to help keep their sites protected as this is a critical security update.
Special thanks to Mitch, from Elegant Themes, for working with us to quickly get a patch out to protect Elegant Themes users.