Headline
CVE-2020-36711: Avada WordPress Theme fixed multiple vulnerabilities.
The Avada theme for WordPress is vulnerable to Stored Cross-Site Scripting via the update_layout function in versions up to, and including, 6.2.3 due to insufficient input sanitization and output escaping. This makes it possible for contributor-level attackers, and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.
Avada, a popular WordPress theme installed on 600,000 websites, was prone to several vulnerabilities affecting version 6.2.2 and below that could allow a low-privileged user to edit, create or delete any page or post on the website.
Avada comes in three parts: a theme (slug: Avada) and two required plugins, Fusion Builder and Fusion Core (slugs: fusion-builder and fusion-core).
Content Injection & Stored XSS
In the “fusion-builder/inc/class-fusion-builder-library.php” script, Avada registers the fusion_builder_update_layout action to load the update_layout function via the AJAX API:
add_action( 'wp_ajax_fusion_builder_update_layout’, [ $this, ‘update_layout’ ] ); … … /** * Save custom layout. */ public function update_layout() {
check_ajax_referer( 'fusion_load_nonce’, ‘fusion_load_nonce’ );
if ( isset( $_POST[‘fusion_layout_id’] ) && ‘’ !== $_POST[‘fusion_layout_id’] && apply_filters( 'fusion_global_save’, true, ‘ajax’ ) ) {
$layout\_id = wp\_unslash( $\_POST\['fusion\_layout\_id'\] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
$content = isset( $\_POST\['fusion\_layout\_content'\] ) ? wp\_unslash( $\_POST\['fusion\_layout\_content'\] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
$to\_replace = addslashes( ' fusion\_global="' . $layout\_id . '"' );
$content = str\_replace( $to\_replace, '', $content );
// Filter nested globals.
$content = apply\_filters( 'content\_save\_pre', $content, $content, $layout\_id );
$post = \[
'ID' => $layout\_id,
'post\_content' => $content,
\];
wp\_update\_post( $post );
} wp_die(); }
The function is used to update the content of the fusion_element or fusion_template post type whose ID is fusion_layout_id. It doesn’t verify if the user is allowed to edit the corresponding post ID nor if the post type is the expected one. The function only checks the fusion_load_nonce security nonce, which is populated by the admin_scripts function in the “fusion-builder/inc/class-fusion-builder.php” script:
add_action( 'admin_enqueue_scripts’, [ $this, ‘admin_scripts’ ] ); … … public function admin_scripts( $hook ) { … … if ( ( ‘post.php’ === $pagenow || ‘post-new.php’ === $pagenow ) && post_type_supports( $typenow, ‘editor’ ) ) { … … // Localize Script. wp_localize_script( 'fusion_builder’, 'fusionBuilderConfig’, [ ‘ajaxurl’ => admin_url( ‘admin-ajax.php’ ), ‘fusion_load_nonce’ => wp_create_nonce( ‘fusion_load_nonce’ ), … … ] ); … …
The nonce is echoed in the source of the HTML page when a logged-in user accesses “post-new.php” to edit or create a new post:
A low-privileged user such as a contributor can copy the nonce and modify any existing page or post on the website. It is also possible to inject JavaScript code by using the [fusion_code] attribute, which is enabled by default:
Arbitrary Post Deletion
Avada registers the fusion_builder_delete_layout action in order to load the delete_layout function:
add_action( 'wp_ajax_fusion_builder_delete_layout’, [ $this, ‘delete_layout’ ] ); … … /** * Delete custom template or element. */ public function delete_layout() {
check_ajax_referer( 'fusion_load_nonce’, ‘fusion_load_nonce’ );
if ( isset( $_POST[‘fusion_layout_id’] ) && ‘’ !== $_POST[‘fusion_layout_id’] ) {
$layout\_id = (int) $\_POST\['fusion\_layout\_id'\];
if ( '' === $layout\_id ) {
die( -1 );
}
wp\_delete\_post( $layout\_id, true );
}
wp_die(); }
Here too, the user capability and the post type aren’t checked, the function relying only on the same security nonce. A logged-in contributor can delete any post or page on the website.
Arbitrary Post Creation
The fusion_builder_save_layout AJAX action used to call the save_layout function is prone to the same type of vulnerability: A logged-in contributor can create a post, select several parameters (post type, post status, slug etc), as well as inject JavaScript code with the [fusion_code] attribute.
Recommendations
Update immediately if you have version 6.2.2 or below installed.
If you are using our web application firewall for WordPress, NinjaFirewall WP Edition (free) and NinjaFirewall WP+ Edition (premium), you are protected against this vulnerability since April 23, 2020.
Timeline
The vulnerability was reported to the authors on April 23, 2020 and a new version 6.2.3 was released on April 24, 2020.
Stay informed about the latest vulnerabilities
- Running WordPress? You can get email notifications about vulnerabilities in the plugins or themes installed on your blog.
- On Twitter: @nintechnet