Avada WordPress Theme fixed multiple vulnerabilities.

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