This blog post is about the Essential Addons for Elementor plugin vulnerability. If you’re a 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 Elementor plugin
The plugin Essential Addons for Elementor (versions $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 that created the user registration form doesn’t have the 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 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
The issue can be patched by simply restricting the role configuration of the user registration form process only to an administrator user. The vendor decides to implement a couple of checks on the registration role field. The patch can be seen here:
Conclusion
For custom user registration processes that allows 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 to directly assign the site’s default registration role and only allow 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 is could be easily exploited by 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 need to be enabled. We also decide to publish this article early since we detect that third party already releasing information regarding this vulnerability.