A severe security flaw in a popular WordPress plugin called Essential Addons for Elementor. The flaw is an unauthenticated privilege escalation vulnerability that allows any unauthenticated user to escalate their privilege to that of any user on the WordPress site. The wordpress vulnerability could be weaponized to reset the password associated with an administrator account and seize full control of the website.
The points we will discuss in this article:
- A severe security flaw has been discovered in a popular WordPress plugin called Essential Addons for Elementor.
- The flaw is an unauthenticated privilege escalation vulnerability that allows any unauthenticated user to escalate their privilege to that of any user on the WordPress site.
- The vulnerability could be weaponized to reset the password associated with an administrator account and seize full control of the website.
- The flaw has been addressed by the plugin maintainers in version 5.7.2 that was shipped on May 11, 2024.
- The flaw is being actively exploited in the wild, and users are advised to update to the latest version as soon as possible.
- The Essential Addons for Elementor plugin has over one million active installations.
- Other malware campaigns that are using compression techniques to conceal the malware and avoid detection are also mentioned.
Table of Contents [TOC]
Essential Addons for Elementor WordPress Plugin
The widely-used Essential Addons for Elementor plugin (free version, versions between 5.4.0 and 5.7.1) has gained immense popularity as one of the most sought-after Elementor addons in the WordPress community. With over 1 million active installations, it is known for its ability to enhance the Elementor page building experience.
With 90+ creative elements and extensions, this WordPress plugin significantly elevates the capabilities of the Elementor page builder. It introduces user-friendly elements specifically crafted to simplify and enhance the design of our WordPress pages and posts, resulting in aesthetically pleasing and user-friendly layouts.
Essential Addons for Elementor Plugin Vulnerability
A concerning security vulnerability has recently been uncovered in Essential Addons for Elementor, a popular WordPress plugin, which has the potential to allow attackers to gain elevated privileges on affected sites.
Tracked as CVE-2024-32243, the issue has been promptly addressed by the plugin maintainers in version 5.7.2, released on May 11, 2024. With over a million active installations, Essential Addons for Elementor has become a target for malicious actors.
Vulnerability Details
Description: Essential Addons for Elementor <= 5.7.1 – Unauthenticated Arbitrary Password Reset to Privilege Escalation
Affected Plugin: Essential Addons for Elementor
Plugin Slug: essential-addons-for-elementor-lite
Affected Versions: <= 5.7.1
CVE ID: CVE-2024-32243
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
Researcher/s: Rafie Muhammed
Fully Patched Version: 5.7.2
Vulnerability came from observing the init hook located in the register_hooks function:
includes/Classes/Bootstrap.php // Login | Register add_action('init', [$this, 'login_or_register_user']);
Let’s see the login_or_register_user function that will be triggered:
includes/Traits/Login_Registration.php public function login_or_register_user() { do_action( 'eael/login-register/before-processing-login-register', $_POST ); // login or register form? if ( isset( $_POST['eael-login-submit'] ) ) { $this->log_user_in(); } else if ( isset( $_POST['eael-register-submit'] ) ) { $this->register_user(); } else if ( isset( $_POST['eael-lostpassword-submit'] ) ) { $this->send_password_reset(); } else if ( isset( $_POST['eael-resetpassword-submit'] ) ) { $this->reset_password(); } do_action( 'eael/login-register/after-processing-login-register', $_POST ); }
If specific $_POST parameters are set, the function will conduct several checks and invoke the appropriate function. The reset_password function is where the underlying vulnerability resides. According to the official commit, this affected function is only present in versions 5.4.0 and later.
includes/Traits/Login_Registration.php public function reset_password() { $ajax = wp_doing_ajax(); $page_id = 0; if ( ! empty( $_POST['page_id'] ) ) { $page_id = intval( $_POST['page_id'], 10 ); } else { $err_msg = esc_html__( 'Page ID is missing', 'essential-addons-for-elementor-lite' ); } $widget_id = 0; if ( ! empty( $_POST['widget_id'] ) ) { $widget_id = sanitize_text_field( $_POST['widget_id'] ); } else { $err_msg = esc_html__( 'Widget ID is missing', 'essential-addons-for-elementor-lite' ); } $rp_data = [ 'rp_key' => ! empty( $_POST['rp_key'] ) ? sanitize_text_field( $_POST['rp_key'] ) : '', 'rp_login' => ! empty( $_POST['rp_login'] ) ? sanitize_text_field( $_POST['rp_login'] ) : '', ]; update_option( 'eael_resetpassword_rp_data_' . esc_attr( $widget_id ), maybe_serialize( $rp_data ), false ); update_option( 'eael_show_reset_password_on_form_submit_' . $widget_id, true, false ); if (!empty( $err_msg )){ if ( $ajax ) { wp_send_json_error( $err_msg ); } update_option( 'eael_resetpassword_error_' . $widget_id, $err_msg, false ); if (isset($_SERVER['HTTP_REFERER'])) { wp_safe_redirect($_SERVER['HTTP_REFERER']); exit(); } } if ( empty( $_POST['eael-resetpassword-nonce'] ) ) { $err_msg = esc_html__( 'Insecure form submitted without security token', 'essential-addons-for-elementor-lite' ); if ( $ajax ) { wp_send_json_error( $err_msg ); } update_option( 'eael_resetpassword_error_' . $widget_id, $err_msg, false ); if (isset($_SERVER['HTTP_REFERER'])) { wp_safe_redirect($_SERVER['HTTP_REFERER']); exit(); } } if ( ! wp_verify_nonce( $_POST['eael-resetpassword-nonce'], 'essential-addons-elementor' ) ) { $err_msg = esc_html__( 'Security token did not match', 'essential-addons-for-elementor-lite' ); if ( $ajax ) { wp_send_json_error( $err_msg ); } update_option( 'eael_resetpassword_error_' . $widget_id, $err_msg, false ); if (isset($_SERVER['HTTP_REFERER'])) { wp_safe_redirect($_SERVER['HTTP_REFERER']); exit(); } } $settings = $this->lr_get_widget_settings( $page_id, $widget_id); if ( is_user_logged_in() ) { $err_msg = isset( $settings['err_loggedin'] ) ? __( Helper::eael_wp_kses( $settings['err_loggedin'] ), 'essential-addons-for-elementor-lite' ) : esc_html__( 'You are already logged in', 'essential-addons-for-elementor-lite' ); if ( $ajax ) { wp_send_json_error( $err_msg ); } update_option( 'eael_resetpassword_error_' . $widget_id, $err_msg, false ); if (isset($_SERVER['HTTP_REFERER'])) { wp_safe_redirect($_SERVER['HTTP_REFERER']); exit(); } } do_action( 'eael/login-register/before-resetpassword-email' ); $widget_id = ! empty( $_POST['widget_id'] ) ? sanitize_text_field( $_POST['widget_id'] ) : ''; // Check if password is one or all empty spaces. $errors = []; if ( ! empty( $_POST['eael-pass1'] ) ) { $post_eael_pass1 = trim( $_POST['eael-pass1'] ); if ( empty( $post_eael_pass1 ) ) { $errors['password_reset_empty_space'] = isset( $settings['err_pass'] ) ? __( Helper::eael_wp_kses( $settings['err_pass'] ), 'essential-addons-for-elementor-lite' ) : esc_html__( 'The password cannot be a space or all spaces.', 'essential-addons-for-elementor-lite' ); } } else { if ( empty( $_POST['eael-pass1'] ) ) { $errors['password_reset_empty_space'] = isset( $settings['err_pass'] ) ? __( Helper::eael_wp_kses( $settings['err_pass'] ), 'essential-addons-for-elementor-lite' ) : esc_html__( 'The password cannot be a space or all spaces.', 'essential-addons-for-elementor-lite' ); } } if( ! empty( $_POST['eael-pass1'] ) && strlen( trim( $_POST['eael-pass1'] ) ) == 0 ){ $errors['password_reset_empty'] = esc_html__( 'The password cannot be empty.', 'essential-addons-for-elementor-lite' ); } // Check if password fields do not match. if ( ! empty( $_POST['eael-pass1'] ) && $_POST['eael-pass2'] !== $_POST['eael-pass1'] ) { $errors['password_reset_mismatch'] = isset( $settings['err_conf_pass'] ) ? __( Helper::eael_wp_kses( $settings['err_conf_pass'] ), 'essential-addons-for-elementor-lite' ) : esc_html__( 'The passwords do not match.', 'essential-addons-for-elementor-lite' ); } if ( ( ! count( $errors ) ) && isset( $_POST['eael-pass1'] ) && ! empty( $_POST['eael-pass1'] ) ) { $rp_login = isset( $_POST['rp_login']) ? sanitize_text_field( $_POST['rp_login'] ) : ''; $user = get_user_by( 'login', $rp_login ); if( $user || ! is_wp_error( $user ) ){ reset_password( $user, sanitize_text_field( $_POST['eael-pass1'] ) );
To prevent the $err_msg from being set, we need to assign a random value to $_POST[‘page_id’] and $_POST[‘widget_id’]. Additionally, we must set $_POST[‘eael-resetpassword-nonce’] as the code verifies the nonce value. To successfully set the password, both $_POST[‘eael-pass1’] and $_POST[‘eael-pass2’] should contain the same password string, as it undergoes a validation check.
Once all the above conditions are met, the code will generate a $rp_login variable based on the value stored in $_POST[‘rp_login’]. Using the get_user_by function, the code will then create a $user object by searching for a matching login (username) value that corresponds to $rp_login.
If the $user object exists and no errors are encountered, the code will proceed to reset the user’s password using the reset_password function.
Now, the question arises as to how we can obtain the essential-addons-elementor nonce value. Interestingly, this nonce value can be found on the main front-end page of the WordPress site since it is assigned in the $this->localize_objects variable through the load_common_asset function.
includes/Classes/Asset_Builder.php // localize object $this->localize_objects = apply_filters( 'eael/localize_objects', [ 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'essential-addons-elementor' ),
In the frontend_asset_load function, the object used for the wp_localize_script call will be the $this->localize_objects variable.
The purpose of the $this->localize_objects variable in the frontend_asset_load function is to serve as the object for the wp_localize_script call.
includes/Classes/Asset_Builder.php
public function frontend_asset_load() {
$handle = 'eael';
$this->post_id = get_the_ID();
$this->elements_manager->get_element_list( $this->post_id );
$this->load_commnon_asset();
$this->register_script();
------------------------------------------------------------------------
wp_localize_script( $handle, 'localize', $this->localize_objects );
}
Unauthenticated Privilege Escalation Vulnerability
According to Rafie Muhammad, a researcher at Patchstack, the plugin suffers from an unauthenticated privilege escalation vulnerability. This flaw enables any unauthorized user to escalate their privileges to match those of any user on the WordPress site.
Exploiting this vulnerability successfully could allow threat actors to reset the password of any user, as long as they possess the knowledge of the targeted user’s username. The flaw is believed to have existed since version 5.4.0.
Consequences of Vulnerability
The consequences of this vulnerability are severe, as it could be exploited to reset the password of an administrator account, granting complete control of the website to the attacker.
Muhammad emphasized the cause of this vulnerability, explaining that the password reset function does not properly validate the reset key and directly changes the password of the specified user.
It is noteworthy that this disclosure follows a similar severe vulnerability discovered by Patchstack in the same plugin over a year ago. That flaw could have been exploited to execute arbitrary code on compromised websites.
Conclusion
A severe security flaw in the Essential Addons for Elementor WordPress plugin that could be exploited to achieve elevated privileges on affected sites. The flaw has been addressed by the plugin maintainers, and users are advised to update to the latest version as soon as possible.
The other malware campaigns that are using compression techniques to conceal the malware and avoid detection. It is essential to stay vigilant and keep software up to date to prevent such vulnerabilities from being exploited.