This blog post is about the vulnerability in Essential Addons for Elementor. If you’re an Essential Addons for Elementor user, please update the plugin to at least version 5.8.9.
Patchstack Developer and Business users are protected from the vulnerability. You can also sign up for the Patchstack Community plan to be notified about vulnerabilities as soon as they become disclosed.
For plugin developers, we have security audit services and Threat Intelligence Feed API for hosting companies.
About the Essential Addons for the Elementor plugin
The plugin Essential Addons for Elementor (versions <= 5.8.8, free version), which has over 1 million active installations, is known as the most popular Elementor addons plugins in WordPress.
This WordPress plugin enhances the Elementor page building experience with 90+ creative elements and extensions. This plugin adds powers to our page builder using the easy-to-use elements that were designed to make our next WordPress page and posts design easier and prettier than ever before.
The security vulnerability in Essential Addons for Elementor
This plugin suffers from an authenticated privilege escalation vulnerability. It allows a user with a minimum of a Contributor role to escalate their privilege to that of any role on the WordPress site including the administrator role.
It is possible to create a custom registration form using the widget provided by Essential addons for Elementor plugin. This vulnerability occurs because a user with the Contributor role is able to set up an arbitrary role for the user registration form. The described vulnerability was fixed in version 5.8.9 and assigned CVE-2023-41955.
The initial step of discovering this vulnerability came from observing the register_user
function that handles the custom user registration widget form process:
public function register_user() {
$ajax = wp_doing_ajax();
---------------------- CUTTED HERE ----------------------
// validate & sanitize the request data
if ( empty( $_POST['eael-register-nonce'] ) ) {
if ( $ajax ) {
wp_send_json_error( __( 'Insecure form submitted without security token', 'essential-addons-for-elementor-lite' ) );
}
if (isset($_SERVER['HTTP_REFERER'])) {
wp_safe_redirect($_SERVER['HTTP_REFERER']);
exit();
}
}
// handle registration...
$user_data = [
'user_login' => $username,
'user_pass' => $password,
'user_email' => $email,
];
if ( ! empty( $_POST['first_name'] ) ) {
$user_data['first_name'] = self::$email_options['firstname'] = sanitize_text_field( $_POST['first_name'] );
}
if ( ! empty( $_POST['last_name'] ) ) {
$user_data['last_name'] = self::$email_options['lastname'] = sanitize_text_field( $_POST['last_name'] );
}
if ( ! empty( $_POST['website'] ) ) {
$user_data['user_url'] = self::$email_options['website'] = esc_url_raw( $_POST['website'] );
}
if ( ! empty( $_POST['eael_phone_number'] ) ) {
$user_data['eael_phone_number'] = self::$email_options['eael_phone_number'] = sanitize_text_field( $_POST['eael_phone_number'] );
}
if( count( $eael_custom_profile_fields_text ) ){
foreach( $eael_custom_profile_fields_text as $eael_custom_profile_field_text_key => $eael_custom_profile_field_text_value ){
self::$email_options[$eael_custom_profile_field_text_key] = '';
if ( ! empty( $_POST[ $eael_custom_profile_field_text_key ] ) ) {
$user_data[$eael_custom_profile_field_text_key] = self::$email_options[$eael_custom_profile_field_text_key] = sanitize_text_field( $_POST[ $eael_custom_profile_field_text_key ] );
}
}
}
$register_actions = [];
$custom_redirect_url = '';
if ( !empty( $settings) ) {
$register_actions = ! empty( $settings['register_action'] ) ? (array) $settings['register_action'] : [];
$custom_redirect_url = ! empty( $settings['register_redirect_url']['url'] ) ? esc_url_raw( $settings['register_redirect_url']['url'] ) : '/';
if ( ! empty( $settings['register_user_role'] ) ) {
$user_data['role'] = sanitize_text_field( $settings['register_user_role'] );
}
---------------------- CUTTED HERE ----------------------
}
$custom_redirect_url = apply_filters( 'eael/login-register/register-redirect-url', $custom_redirect_url, $this );
$user_data = apply_filters( 'eael/login-register/new-user-data', $user_data );
do_action( 'eael/login-register/before-insert-user', $user_data );
$user_default_role = get_option( 'default_role' );
if(!empty($user_default_role) && empty($user_data['role'])){
$user_data['role'] = $user_default_role;
}
if ('administrator' == strtolower($user_data['role'])) {
$user_data['role'] = !empty($settings['register_user_role']) ? wp_strip_all_tags( $settings['register_user_role'] ) : get_option('default_role');
}
$user_id = wp_insert_user( $user_data );
---------------------- CUTTED HERE ----------------------
Notice that we can set the $user_data['role']
to the value of $settings['register_user_role']
. The $user_data
itself comes from the user input but we cannot control the role
parameter, while the $settings
comes from the user registration form widget setting.
There is also no protection on the register_user_role
setting configuration. The code only displays the option of the site’s default role if the user who created the user registration form doesn’t have permission to create users. This can be seen from init_content_register_options_controls
function:
protected function init_content_register_options_controls() {
---------------------- CUTTED HERE ----------------------
if(current_user_can('create_users')){
$user_role = $this->get_user_roles();
}else{
$user_role = [
get_option( 'default_role' ) => ucfirst(get_option( 'default_role' ))
];
}
$this->add_control( 'register_user_role', [
'label' => __( 'New User Role', 'essential-addons-for-elementor-lite' ),
'type' => Controls_Manager::SELECT,
'default' => '',
'options' => $user_role,
'separator' => 'before',
] );
$this->end_controls_section();
}
As we can see on the UI, a user with a Contributor role only provided the role option of the site’s default role. But the restriction only exists on the front-end and the user can still supply any role to the field setting.
The patch for vulnerability in Essential Addons for Elementor
The vulnerability in Essential Addons for Elementor can be patched by simply restricting the role configuration of the user registration form process only to an administrator user. The vendor decided to implement a couple of checks on the registration role field. The patch can be seen here:
Conclusion
For custom user registration processes that allow a user other than an administrator to assign a custom registration role, make sure to secure the registration role configuration on the form.
We recommend directly assigning the site’s default registration role and only allowing a user with the administrator role to adjust this value or create a new user capability to assign a custom role on the user registration form.
Disclosure Note
Note that this vulnerability could be easily exploited by the Contributor role user without any additional requirement such as publishing capabilities since the form could be submitted in a drafted state.
The only configuration needed is the user registration feature in the WordPress site and the user registration form widget from Essential Addons for Elementor needs to be enabled. We also decided to publish this article early since we detected that a third party already releasing information regarding this vulnerability.
Timeline
Help us make the Internet a safer place
Making the WordPress ecosystem more secure is a team effort, and we believe that plugin developers and security researchers should work together.
- If you’re a plugin developer, join our mVDP program that makes it easier to report, manage, and address vulnerabilities in your software.
- If you’re a security researcher, join Patchstack Alliance to report vulnerabilities & earn rewards.